Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

update() does not work for models created via lapply()

Tags:

r

lapply

scoping

I would like to use lapply() to compute several models in R, but it seems that the update() function can't handle models generated through lapply().

A minimal example:

d1 <- data.frame(y = log(1:9), x = 1:9, trt = rep(1:3, each = 3))

f <- list(y ~ 1, y ~ x, y ~ trt)

modsa <- lapply(f, function(formula) glm(formula, data = d1))
modsb <- lapply(f, glm, data = d1)

update(modsa[[1]], data = d1[1:7, ])
#> Error: object of type 'closure' is not subsettable
update(modsb[[1]], data = d1[1:7, ])
#> Error in FUN(formula = X[[i]], data = d1[1:7, ]): could not find function "FUN"

Is there a way that allows update() to deal with models generated through lapply()?

like image 460
Heidi Avatar asked Jun 06 '18 08:06

Heidi


2 Answers

The error is occurring because the call elements of the glm objects are being overwritten by the argument name passed to the anonymous function

modsa <- lapply(f, function(x) glm(x, data = d1))

modsa[[1]]$call
 glm(formula = x, data = d1)

#compare with a single instance of the model    
moda1<-glm(y ~ 1, data=d1)

moda1$call
 glm(formula = y ~ 1, data = d1)

If you add back in the formula, it will correctly recreate the call

update(modsa[[1]], data = d1[1:7, ], formula=f[[1]])

This doesn't work for the second instance, but you can see that if you manually update the call element the update functionality is rescued.

modsb[[1]]$call<-getCall(moda1)

update(modsb[[1]], data = d1[1:7, ])
like image 145
Esther Avatar answered Nov 19 '22 19:11

Esther


Esther is correct, the problem is with the call element of glm. From ?update:

‘update’ will update and (by default) re-fit a model. It does this by extracting the call stored in the object, updating the call and (by default) evaluating that call.

As already mentioned, one can update including the formula as well:

update(modsa[[1]], data = d1[1:7, ], formula=f[[1]])

If for some reason this is not convenient, here is how to run your lapply() and have it assign directly the correct formula to the call element:

modsa <- lapply(f, function(formula) eval(substitute(glm(F, data = d1), list(F=formula))))

This substutites the respective formula to the glm call, and then evaluates it. With this long one-liner you can run update(modsa[[1]], data = d1[1:7, ]) with no problem.

like image 2
Theodore Lytras Avatar answered Nov 19 '22 18:11

Theodore Lytras