我正在尝试使用purrr :: map制作lm对象的列表。以mtcars为例:
vars <- c('hp', 'wt', 'disp')
map(vars, ~lm(mpg~.x, data=mtcars))
Run Code Online (Sandbox Code Playgroud)
错误:model.frame.default(formula = mpg〜.x,data = mtcars,drop.unused.levels = TRUE)中的错误:可变长度不同(为'.x'找到)
我也尝试过:
map(vars, function(x) {x=sym(x); lm(mpg~!!x, data=mtcars)})
Run Code Online (Sandbox Code Playgroud)
我收到错误消息:
Error in !x : invalid argument type
Run Code Online (Sandbox Code Playgroud)
谁能告诉我我做错了什么?提前致谢。
通常的方法是将paste
公式作为字符串组合在一起,通过map
ping 转换它们as.formula
(您不能创建公式的向量;它必须是列表),然后单击map
lm
。如果愿意,可以将所有功能组合到一个调用中,但是我更喜欢映射单个函数,这使代码更易于阅读:
library(purrr)
c('hp', 'wt', 'disp') %>%
paste('mpg ~', .) %>%
map(as.formula) %>%
map(lm, data = mtcars)
#> [[1]]
#>
#> Call:
#> .f(formula = .x[[i]], data = ..1)
#>
#> Coefficients:
#> (Intercept) hp
#> 30.09886 -0.06823
#>
#>
#> [[2]]
#>
#> Call:
#> .f(formula = .x[[i]], data = ..1)
#>
#> Coefficients:
#> (Intercept) wt
#> 37.285 -5.344
#>
#>
#> [[3]]
#>
#> Call:
#> .f(formula = .x[[i]], data = ..1)
#>
#> Coefficients:
#> (Intercept) disp
#> 29.59985 -0.04122
Run Code Online (Sandbox Code Playgroud)
实际上没有必要进行调用,map(as.formula)
因为lm
它会强制将其转换为公式,但是并非所有模型都如此慷慨(例如mgcv::gam
)。
这种方法的缺点是,对象中列出的调用看起来很时髦,但是系数告诉您到底哪个是足够容易的。一个有用的替代方法是将公式保留为data.frame的一列中的字符串,将模型保留为list列中的模型,例如
library(tidyverse)
data_frame(formula = paste('mpg ~', c('hp', 'wt', 'disp')),
model = map(formula, lm, data = mtcars))
#> # A tibble: 3 x 2
#> formula model
#> <chr> <list>
#> 1 mpg ~ hp <S3: lm>
#> 2 mpg ~ wt <S3: lm>
#> 3 mpg ~ disp <S3: lm>
Run Code Online (Sandbox Code Playgroud)