17

Is there an R data structure into which I can store a number of lm or lmer or gam objects? J has boxed arrays, and one can put pretty much anything into the cells of such a boxed array. I think that's what I'm looking for in R.

I've tried lists and data frames, to no avail; I thought lists might work.

> testlist <- list()
> testlist[1] <- subject1.2008.gam
Warning message:
In testlist[1] <- subject1.2008.gam :
  number of items to replace is not a multiple of replacement length
> 

Alternatively, is there a way to create and use a variable name on the LHS of <-?

Finally, perhaps you have a better idiom for me to consider. I'm trying to create a collection of GAM models over a set of subjects and years, for example. Later, I want to be able to plot or predict from those models, so I think I need to keep the full model around. Because I want to be able to use this code with different data sets later, I'd like not to hard-code the names of the gam objects nor their number.

While I started by putting the gam() call in a loop, I think one of the apply() functions might work better, but I still need a place to store the output.

Rui Barradas
  • 70,273
  • 8
  • 34
  • 66
Bill
  • 533
  • 1
  • 4
  • 16
  • You might also want to look into plyr, which makes this sort of model fitting very very easy. – hadley Apr 09 '11 at 23:24

3 Answers3

25

You need the [[ operator for lists, try

testlist[[1]] <- subject1.2008.gam

The other usual tip is that you may want to pre-allocate if you know how many elements you may have, I often do

testlist <- vector(mode="list", length=N)

for a given N.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • Both answers are essentially the same and seem to solve my problem; thanks! – Bill Apr 08 '11 at 19:51
  • You can also use a string for the list index - this is much more useful and readable later. e.g. `models[[model_name]] <- model`. – metakermit Nov 06 '13 at 16:14
  • Doing something like testlist[[1]] <- subject1.2008.gam wasn't working for my lm() model objects. I wasn't able to then use fitted(testlist[[1]]), for example. Instead, I used this construction: testlist <- list(subject1.2008.gam=subject1.2008.gam) – ginko Jan 10 '19 at 00:04
3

Use [[ to access the list elements:

library(mgcv)
set.seed(0) ## simulate some data... 
dat <- gamSim(1,n=400,dist="normal",scale=2)

mods <- vector(mode = "list", length = 3)
for(i in seq_along(mods)) {
    mods[[i]] <- gam(y ~ s(x0) + s(x1) + s(x2) + s(x3), data = dat)
}

Giving:

> str(mods, max = 1)
List of 3
 $ :List of 43
  ..- attr(*, "class")= chr [1:3] "gam" "glm" "lm"
 $ :List of 43
  ..- attr(*, "class")= chr [1:3] "gam" "glm" "lm"
 $ :List of 43
  ..- attr(*, "class")= chr [1:3] "gam" "glm" "lm"
Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453
2

The other answers show how to use an index and [[ ]] but you can also do something like

x1  <- 1:10  ; y1  <-  30*x1 + rnorm(10)
x2  <- rnorm(20)  ; y2  <- 30*x2 + 100 + rnorm(20)
lm1 <- lm(y1 ~ x1); lm2 <- lm(y2 ~ x2) 

testlist <- list( A = lm1, Z = lm2 ) 
testlist$Z
testlist$Z$model$y2
Henry
  • 6,704
  • 2
  • 23
  • 39