0

Goal: Run three regression models with three different outcome variables, as seen below, but ideally in a more efficient way than seen in the model1, model2, model3 version seen in the last three lines.

Specific question: How can I write a function that iterates over the set of dv's and creates model + # indicator as an object (e.g. model1, model2, etc.) AND switches the dv (e.g. dv1, dv2, etc...)? I assume there is a forloop and function solution to this but I am not getting it...

mydf <- data.frame(dv1 = rnorm(100),
               dv2 = rnorm(100),
               dv3 = rnorm(100),
               iv1 = rnorm(100),
               iv2 = rnorm(100),
               iv3 = rnorm(100))

mymodel <- function(dv, df) {
lm(dv ~ iv1 + iv2 + iv3, data = df)
}

model1 <- mymodel(dv = mydf$dv1, df = mydf)
model2 <- mymodel(dv = mydf$dv2, df = mydf)
model3 <- mymodel(dv = mydf$dv3, df = mydf)
tall_table
  • 311
  • 3
  • 11
  • Possibly helpful: https://www.r-bloggers.com/how-to-create-a-loop-to-run-multiple-regression-models/ – MrFlick Nov 26 '18 at 21:13

2 Answers2

1

Here's another approach using the tidyverse packages, since dplyr has more or less supplanted plyr.

library(tidyverse)

mydf <- data.frame(dv1 = rnorm(100),
                   dv2 = rnorm(100),
                   dv3 = rnorm(100),
                   iv1 = rnorm(100),
                   iv2 = rnorm(100),
                   iv3 = rnorm(100))

mymodel <- function(df) {
  lm(value ~ iv1 + iv2 + iv3, data = df)
}

mydf %>% 
  gather("variable","value", contains("dv")) %>% 
  split(.$variable) %>% 
  map(mymodel) 

#> $dv1
#> 
#> Call:
#> lm(formula = value ~ iv1 + iv2 + iv3, data = df)
#> 
#> Coefficients:
#> (Intercept)          iv1          iv2          iv3  
#>    -0.04516     -0.04657      0.08045      0.02518  
#> 
#> 
#> $dv2
#> 
#> Call:
#> lm(formula = value ~ iv1 + iv2 + iv3, data = df)
#> 
#> Coefficients:
#> (Intercept)          iv1          iv2          iv3  
#>    -0.03906      0.16730      0.10324      0.02500  
#> 
#> 
#> $dv3
#> 
#> Call:
#> lm(formula = value ~ iv1 + iv2 + iv3, data = df)
#> 
#> Coefficients:
#> (Intercept)          iv1          iv2          iv3  
#>    0.018492    -0.162563     0.002738     0.179366

Created on 2018-11-26 by the reprex package (v0.2.1)

Jake Kaupp
  • 7,892
  • 2
  • 26
  • 36
0

You could convert your data.frame to long form, with all the dv values in one column and then use plyr's dlply to create the lms. This splits the data.frame on the specified column ("dvN") and applys the function to each and returns a list of lms. I have changed the function slightly to make it just take a data.frame, not the column separately.

Hope this gives what you need.

library(plyr)
library(tidyr)

mydf_l <- gather(mydf, dvN, Value, 1:3)

mymodel2 <- function(df) {
  lm(Value ~ iv1 + iv2 + iv3, data = df)
}

allmodels <- dlply(mydf_l, .(dvN), mymodel2)
Sarah
  • 3,022
  • 1
  • 19
  • 40