6

I have a list of objects that I've created manually, like this:

rand1 <- rnorm(1e3)
rand2 <- rnorm(1e6)

myObjects <- NULL
myObjects[[1]] <-rand1
myObjects[[2]] <-rand2
names(myObjects) <- c("rand1","rand2")

I'm working on some code that bundles up objects and puts them up in S3. Then I have code in EC2 that I want to grab the myObjects list and 'unbundle' it automatically. In this example the list only has two objects and the names are known, but how do I code this to handle lists of any length and any names?

#pseudo code
for each thing in myObjects
  thing <- myObjects[[thing]]

I can't quite figure out how to take names(myObjects)[1] and turn it into the name of an object for which I will assign the contents of myObjects[[1]]. I can handle the looping but creating each object kinda has me hung. I'm sure this is quite simple, but I can't quite grok it.

JD Long
  • 59,675
  • 58
  • 202
  • 294
  • Related: http://stackoverflow.com/questions/2590043/creating-a-series-of-vectors-from-a-vector, http://stackoverflow.com/questions/2679193/how-to-name-variables-on-the-fly-in-r, http://stackoverflow.com/questions/2899581/assign-subset-of-parent-table-to-objects-in-r, http://stackoverflow.com/questions/2907896/how-to-assign-to-the-names-attribute-of-the-value-of-a-variable-in-r – Marek Jun 22 '10 at 15:20
  • 1
    Thanks for the links Marek. This becomes a 'corner solution' of sorts for search. Once I know the function that does what I want, it's so much easier to find related questions. The really hard bit is figuring out how to get there with only a brief description of the problem! – JD Long Jun 22 '10 at 15:39

3 Answers3

12

You can use assign:

for(i in 1:length(myObjects)) assign(names(myObjects)[i], myObjects[[i]])
Shane
  • 98,550
  • 35
  • 224
  • 217
  • assign()... that's the piece I was missing! thanks to both you and Richie for pointing me in the right direction. – JD Long Jun 22 '10 at 15:40
  • 4
    `seq_along(myObjects)` is a little safer if `length(myObjects) == 0` – hadley Jun 22 '10 at 21:39
  • 1
    @hadley: Thanks! seq_along() is a great find. As in the following examples: bad = `for(i in 1:length(NULL)) print(i)`, good = `for(i in seq_along(NULL)) print(i)` – Shane Jun 23 '10 at 14:16
9

attach(myObjects)

hadley
  • 102,019
  • 32
  • 183
  • 245
  • 2
    I had basically taken attach() out of my vocabulary because I found that the way most folks use it results in kinda crappy code that's hard to track. So I didn't even think of using it in this case. But now that you mention it, I think it's a really good solution. Thanks for helping me think outside of my small box. – JD Long Jun 22 '10 at 22:02
  • 5
    I don't think it's ever a good idea to use attach. But if you're going to use it, use it, don't write your own version of it. – hadley Jun 23 '10 at 13:06
  • 2
    See also: `with(myObjects, { ... })` for a faster and safer alternative to `attach`. – Richie Cotton Jun 23 '10 at 13:58
6

To expand Shane's answer:

mapply(assign, names(myObjects), myObjects, MoreArgs=list(envir = globalenv())

(You may wish to change globalenv() to another environment.)

Richie Cotton
  • 118,240
  • 47
  • 247
  • 360
  • very good idea about changing environments. I should use that. That's a bonus idea! – JD Long Jun 22 '10 at 15:42
  • In this example I see the objects rand1 and rand2 are created, but it also seems to output the myObjects object as well. If I assign the results of this mapply() to an object I end up with a copy of myObjects PLUS rand1 and rand2. Kinda noisy and seems inefficient. Should this be a different flavor of apply? – JD Long Jun 22 '10 at 15:59