Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applying lm with map2

Tags:

r

dplyr

purrr

lm

I'm trying to learn purrr's map functions by using map2 to apply lm. Using a subset of the mtcars data set, I create a data frame with combinations of the variables' names, like this:

# Load libraries
library(dplyr)
library(purrr)

# Subset data
df <- mtcars %>% select(mpg:qsec) 

# Get variable names
car_vars <- colnames(df)

# Create data frame of variable names
foo <- combn(car_vars, 2) %>% t %>% data.frame

# > head(foo)
#    X1   X2
# 1 mpg  cyl
# 2 mpg disp
# 3 mpg   hp
# 4 mpg drat
# 5 mpg   wt
# 6 mpg qsec

Next, I have a function that takes the name of two variables and fits a linear model:

# Fit model
fit_lm <- function(c1, c2){
  lm(paste(c1, c2, sep = "~"), data = df)
} 

I can apply this with map2 like so:

# Fit all the models 
map2(foo$X1, foo$X2, fit_lm)

giving a list of lm objects that looks something like this when printed:

# [[1]]
# 
# Call:
#   lm(formula = paste(c1, c2, sep = "~"), data = df)
# 
# Coefficients:
#   (Intercept)          cyl  
# 37.885       -2.876  

Great! Now, here's where I stumble. I'd like to add these lm objects as a column in my data frame, so I conveniently have the variable names in the same row as the model itself. So, I use dplyr's mutate with map2.

# Not so successful
foo %>% mutate(mods = map2(X1, X2, fit_lm))

The mods column produced has class NULL rather than lm and looks a bit like a dput of a lm object, unlike my previous (successful) attempt. Clearly, I've misunderstood how map2 works. Can someone explain my mistake?

like image 699
Lyngbakr Avatar asked May 29 '26 19:05

Lyngbakr


1 Answers

In terms of the result itself, what you did is fine:

foo <- foo %>% mutate(mods = map2(X1, X2, fit_lm))
str(foo, max.level = 1)
# 'data.frame': 21 obs. of  3 variables:
#  $ X1  : Factor w/ 6 levels "cyl","disp","drat",..: 5 5 5 5 5 5 1 1 1 1 ...
#  $ X2  : Factor w/ 6 levels "cyl","disp","drat",..: 1 2 4 3 6 5 2 4 3 6 ...
#  $ mods:List of 21

The problem is simply that

class(foo)
# [1] "data.frame"

and such complex lists as those of lm class are printed terribly with print.data.frame. So, as to instead see the result nicely with print.tbl, we only need to convert foo to tibble:

foo <- as.tbl(foo)
foo
# A tibble: 21 x 3
#    X1    X2    mods    
#    <fct> <fct> <list>  
#  1 mpg   cyl   <S3: lm>
#  2 mpg   disp  <S3: lm>
#  3 mpg   hp    <S3: lm>
#  4 mpg   drat  <S3: lm>
#  5 mpg   wt    <S3: lm>
#  6 mpg   qsec  <S3: lm>
#  7 cyl   disp  <S3: lm>
#  8 cyl   hp    <S3: lm>
#  9 cyl   drat  <S3: lm>
# 10 cyl   wt    <S3: lm>
# … with 11 more rows
like image 131
Julius Vainora Avatar answered May 31 '26 09:05

Julius Vainora



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!