How to pass more than one argument to laply?

68 Views Asked by At

I would like to run a series of regression models and put the output relating to a particular covariate into an array. I've been able to do this with laply from the plyr package, like this:

set.seed(1)
df <- data.frame(x1 = rnorm(100, 0, 1), 
                 x2 = rnorm(100, 0, 1),
                 y1 = rnorm(100, 0, 1), 
                 y2 = rnorm(100, 0, 1), 
                 t2 = sample(0:1, 100, replace = TRUE), 
                 t1 = sample(0:1, 100, replace = TRUE))

run_regressions <- function(model) {
  model <- glm(model, data = df)
  return(summary(model)$coefficients[2,])
}

models <- list("y1 ~ t1 + x1",
               "y2 ~ t2 + x1 + x2")

results <- laply(models, run_regressions)
results

I would now like to extend this so that I can pass the different elements of the regression models to the run_regressions function separately. The regression function would be defined like

run_regressions2 <- function(outcome, treatment, covariates) {
  model <- glm(paste(outcome, " ~ ", treatment, " + ", covariates), data = df)
  return(summary(model)$coefficients[2,])
}

with the specific models to run specified as something like

models <- list(c("y1", "t1", "x1"),
               c("y2", "t2", "x1 + x2"))

Is there some way to use laply or another function to achieve this?

I've tried searching the plyr documentation for similar examples and searching SO for similar questions, but have not come up with anything.

2

There are 2 best solutions below

0
Ronak Shah On

As mentioned by @jdobres , plyr has been long retired. There are lot of modern replacements for it like dplyr and purrr package.

One option would be to use lapply in base R. In such case, the first case would change to

models <- list("y1 ~ t1 + x1", "y2 ~ t2 + x1 + x2")
results <- lapply(models, run_regressions)
results

#[[1]]
#   Estimate  Std. Error     t value    Pr(>|t|) 
#-0.42628388  0.20517578 -2.07765211  0.04038316 

#[[2]]
#  Estimate Std. Error    t value   Pr(>|t|) 
#-0.2966993  0.1991987 -1.4894639  0.1396433 

In the second, case you can continue using lapply -

models <- list(c("y1", "t1", "x1"),c("y2", "t2", "x1 + x2"))

lapply(seq_along(models), \(x) 
      run_regressions2(models[[x]][1], models[[x]][2], models[[x]][3]))

Or more generally using do.call for any number of arguments.

lapply(seq_along(models), \(x) do.call(run_regressions2, as.list(models[[x]])))
0
Robert Hacken On

An alternative to @Ronak Shah's final solution without having to use models twice would be:

lapply(lapply(models, as.list), do.call, what=run_regressions2)

The inner lapply changes models into a list of lists which are then used as arguments to do.call.