4

I have seen an example of list apply (lapply) that works nicely to take a list of data objects, and return a list of regression output, which we can pass to Stargazer for nicely formatted output. Using stargazer with a list of lm objects created by lapply-ing over a split data.frame

library(MASS)
library(stargazer)
data(Boston)

by.river <- split(Boston, Boston$chas)
class(by.river)

fit <- lapply(by.river, function(dd)lm(crim ~ indus,data=dd))
stargazer(fit, type = "text")

What i would like to do is, instead of passing a list of datasets to do the same regression on each data set (as above), pass a list of independent variables to do different regressions on the same data set. In long hand it would look like this:

fit2 <- vector(mode = "list", length = 2)
fit2[[1]] <- lm(nox ~ indus, data = Boston)
fit2[[2]] <- lm(crim ~ indus, data = Boston)
stargazer(fit2, type = "text")

with lapply, i tried this and it doesn't work. Where did I go wrong?

myvarc <- c("nox","crim")
class(myvarc)
myvars <- as.list(myvarc)
class(myvars)
fit <- lapply(myvars, function(dvar)lm(dvar ~ indus,data=Boston))
stargazer(fit, type = "text")
Community
  • 1
  • 1
Mark Neal
  • 996
  • 16
  • 52
  • 2
    This works, but is not neat (uses column numbers not names, doesn't retain names for headings into stargazer output) `fit3 = lapply(Boston[,c(1,5)], function(x)(lm(x ~ Boston$indus))) stargazer(fit3, type = "text")` – Mark Neal Feb 07 '17 at 23:52
  • 2
    The problem solved below. However the labels don't flow nicely to Stargazer. This code will fix that.`stargazer(fit, type = "text", dep.var.labels.include = FALSE, column.labels = myvarc)` – Mark Neal Feb 08 '17 at 00:37

4 Answers4

6

Consider creating dynamic formulas from string:

fit <- lapply(myvars, function(dvar)
    lm(as.formula(paste0(dvar, " ~ indus")),data=Boston))
Parfait
  • 104,375
  • 17
  • 94
  • 125
  • 2
    Similarly, with `reformulate`, you could do `fit <- lapply(myvars, function(dvar) lm(reformulate("indus", dvar)),data=Boston))`. – lmo Feb 08 '17 at 00:44
2

This should work:

fit <- lapply(myvars, function(dvar) lm(eval(paste0(dvar,' ~ wt')), data = Boston))
GGamba
  • 13,140
  • 3
  • 38
  • 47
  • 2
    While this works as well as Parfait's, Parfait's `as.formula` makes more sense to read. I suspect though, the use of the more general `eval()` is more flexible, and could be helpful in some other cases. Cheers, – Mark Neal Feb 08 '17 at 00:36
  • In R, `eval(parse...))` though here `eval(paste0(...))` is used but same concept holds of evaluating string expressions is generally not recommended for various reasons (i.e., security, consistency). See [here](http://stackoverflow.com/questions/13649979/what-specifically-are-the-dangers-of-evalparse) and [here](http://stackoverflow.com/questions/1743698/evaluate-expression-given-as-a-string). – Parfait Feb 08 '17 at 02:43
  • 2
    Thanks for the education! Cheers, - – Mark Neal Feb 08 '17 at 04:19
  • Thanks @Parfait for the links – GGamba Feb 08 '17 at 07:09
2

You can also use a dplyr & purrr approach, keep everything in a tibble, pull out what you want, when you need it. No difference in functionality from the lapply methods.

library(dplyr)
library(purrr)
library(MASS)
library(stargazer)

var_tibble <- tibble(vars = c("nox","crim"), data = list(Boston)) 

 analysis <- var_tibble %>% 
  mutate(models = map2(data, vars, ~lm(as.formula(paste0(.y, " ~ indus")), data = .x))) %>% 
  mutate(tables = map2(models, vars, ~stargazer(.x, type = "text", dep.var.labels.include = FALSE, column.labels = .y)))
Jake Kaupp
  • 7,892
  • 2
  • 26
  • 36
2

You can also use get():

# make a list of independent variables
  list_x <- list("nox","crim")

# create regression function
  my_reg <- function(x) { lm(indus ~ get(x), data = Boston) }

# run regression
  results <- lapply(list_x, my_reg)
rafa.pereira
  • 13,251
  • 6
  • 71
  • 109