14

I'm trying to use assign values in an object in a list. What I want to do is change some elements. For example:

x <- list()
x$test <- 1
assign("x$test", 2)
x$test == 1
     [1] TRUE

Any thoughts? I need to use assign because I am building a function which will take the names of the objects within the list (x) as inputs.

Rob
  • 26,989
  • 16
  • 82
  • 98
mike
  • 22,931
  • 31
  • 77
  • 100
  • Note there's a big difference between `x$test` and `x[['test']]`. See the doc on [`extract(..., drop=TRUE)`](https://stat.ethz.ch/R-manual/R-devel/library/base/html/Extract.html) – smci Apr 28 '16 at 13:37

4 Answers4

16

Looks like you're out of luck. From the help file:

‘assign’ does not dispatch assignment methods, so it cannot be used to set elements of vectors, names, attributes, etc.

Note that assignment to an attached list or data frame changes the attached copy and not the original object: see ‘attach’ and ‘with’.

If you're passing names(x) as input, couldn't you use:

nms <- names(x)
for ( n in nms )
    x[[n]] <- 'new_value'

Also, are you intending for your function to modify some global variable? e.g.:

x <- list(test=1)

f <- function(...)
   x$test <- 2

f() # want x$test = 2 ??

Because this won't work (scope problems). You can make it work with a bit of footwork (<<-), but this is generally considered bad practice as it's easy to intrtoduce unintentional bugs into your code.

If you could give an example of why you want this function/what purpose it will serve, we could help you find an alternative solution.

mathematical.coffee
  • 55,977
  • 11
  • 154
  • 194
  • Great, thanks so much -- I was not aware that I could use the [[n]] syntax, which is totally sufficient. Really appreciate the info. – mike Mar 05 '12 at 04:01
11

See what happens when you assign to "x$test":

x <- list()
x$test <- 1
assign("x$test", 2)
ls()
[1] "x"      "x$test"

The element "test" in "x" is still 1, and you extract it with x$test but get("x$test") will be the value 2 from that name.

Why not just use the names directly? I.e.

this.name <- "test"
x[[this.name]] <- 2
mdsumner
  • 29,099
  • 6
  • 83
  • 91
  • I don't know why the other answer has been accepted, but as mdsumner says, why not using the name directly? that works absolutely flawless. – user1052080 Dec 02 '13 at 19:04
  • assign() allows you to specify the environment in which the assignment happens, which can be very helpful. This is in contrast to <<- which only assigns to the global environment. So, x[[name]] is not as general a solution as assign(x$name, value, envir = my_env) would be. – William Doane Aug 02 '17 at 13:08
2

Another solution is:

x <- list()
x$test <- 1
assign("x$test", 2)
x$test == 1
TRUE
eval(parse(text="x$test<-2"))
x$test == 1
FALSE

The eval(parse(text="")) command can be very useful in this context.

Sincerely

Parvin Gasimzade
  • 25,180
  • 8
  • 56
  • 83
  • 5
    To paraphrase Thomas Lumley : "If the answer is parse() you should usually rethink the question." Avoid constructs like this at all times if there's a more sensible solution. Here that solution is `[[` – Joris Meys Jun 28 '12 at 12:59
1

Have you tried <<- ? I used this to assign names and values to a list from within a function in a post yesterday (see "Combine a series of data frames and create new columns for data in each").

Ana Nimbus
  • 635
  • 3
  • 16
Tyler Rinker
  • 108,132
  • 65
  • 322
  • 519