Danielle van Os
Danielle van Os

Reputation: 11

R assign to an evaluated object

I want to be able to change the cell of a dataframe by referring to the object's name, rather than to the object itself, but when I attempt do do so it results in the warning could not find function "eval<-".

I can change a cell of a standard dataframe using the code below:

my_object = tibble(x = c("Hello", "Goodbye"), 
                   y = c(1,2))

object[2,1] <- "Bye"

But I am having trouble doing the same when using the object's name. I can evaluate the object using its name and extract the relevant cell:

object_name = "my_object"
eval(sym(object_name))[2, 1]

But I can't assign a new variable to the object (error: could not find function "eval<-"):

eval(sym(object_name))[2, 1] <- "Bye"

Upvotes: 1

Views: 406

Answers (3)

G. Grothendieck
G. Grothendieck

Reputation: 269481

1) environments

1a) Subscript the current environment with object_name.

e <- environment()
e[[object_name]][2, 1] <- "Bye"

1b) or as one line:

with(list(e = environment()), e[[object_name]][2, 1] <- "Bye")

1c) If my_object is in the global environment, as in the question, it could optionally be written as:

.GlobalEnv[[object_name]][2, 1] <- "Bye"

2) assign We could use assign like this:

assign(object_name, within(get(object_name), x[2] <- "Bye"))

3) without clobbering

3a) If what you really want is to create a new data frame without clobbering the input:

library(dplyr)
mutate(get(object_name), across(1, ~ replace(., 2, "Bye")))

3b) or if we knew that the column name was x then:

library(dplyr)
mutate(get(object_name), x = replace(x, 2, "Bye"))

3c) or without dplyr

within(get(object_name), x[2] <- "Bye")

Upvotes: 2

Skaqqs
Skaqqs

Reputation: 4140

If you want to define your command as a string, parse it as an expression, and then use eval:

eval(parse(text=paste0(object_name,"[2,1]<-'Bye'")))

> object
      x y
1 Hello 1
2   Bye 2

Upvotes: 1

Allan Cameron
Allan Cameron

Reputation: 173793

You can use get() instead of eval(sym())to obtain an object by name. You can also use the [<- function to write a value to it without requiring an intermediate copy:

my_object = dplyr::tibble(x = c("Hello", "Goodbye"), 
                   y = c(1,2))

object_name = "my_object"

`[<-`(get(object_name), 2, 1, value ="Bye")
#> # A tibble: 2 x 2
#>   x         y
#>   <chr> <dbl>
#> 1 Hello     1
#> 2 Bye       2

Created on 2022-06-02 by the reprex package (v2.0.1)

Upvotes: 5

Related Questions