5

我经常喜欢拟合和检查与 R 数据框中的两个变量相关的多个模型。

我可以使用这样的语法来做到这一点:

require(tidyverse)
require(broom)
models <- list(hp ~ exp(cyl), hp ~ cyl)
map_df(models, ~tidy(lm(data=mtcars, formula=.x)))

但我习惯了管道语法,并希望能够做到这样的事情:

mtcars %>% map_df(models, ~tidy(lm(data=., formula=.x)))

这清楚地表明我正在“开始”mtcars然后对其进行处理以生成我的输出。但是那个语法不起作用,给出一个错误Error: Index 1 must have length 1

有没有办法以purrr:map()一种我可以通过管道mtcars输入的方式来编写我的函数以获得与上面的工作代码相同的输出?IE

mtcars %>% <<<something>>>
4

3 回答 3

4

tl/博士:mtcars %>% {map_df(models, function(.x) tidy(lm(data=., formula=.x)))}

或者mtcars %>% map_df(models, ~tidy(lm(..1,..2)), ..2 = .)


您尝试过的解决方案有两个问题。

第一个是如果你想把点放在一个不寻常的地方,你需要使用花括号。

library(magrittr)
1 %>% divide_by(2)   # 0.5     -> this works
1 %>% divide_by(2,.) # 2       -> this works as well
1 %>% divide_by(2,mean(.,3))   #  this doesn't    
1 %>% divide_by(.,2,mean(.,3)) #  as it's equivalent to this one
1 %>% {divide_by(2,mean(.,3))} #  but this one works as it forces all dots to be explicit.

第二个是你不能以~你想要的方式使用带有公式的点,尝试map(c(1,2), ~ 3+.)map(c(1,2), ~ 3+.x)(甚至map(c(1,2), ~ 3+..1))你会看到你得到相同的结果。当您在~公式中使用点时,它不再链接到管道函数。

为了确保点被解释为mtcars您需要使用良好的旧function(x) ...定义。

这有效:

mtcars %>% {map_df(models, function(.x) tidy(lm(data=., formula=.x)))}

最后,作为奖励,这是我想出的,试图找到一个没有花括号的解决方案:

mtcars %>% map(models,lm,.) %>% map_df(tidy)
mtcars %>% map_df(models, ~tidy(lm(..1,..2)), ..2 = .)
于 2018-02-05T08:53:14.373 回答
2

这应该有效,并且不涉及functions 或的复杂性{}。一个纯粹的purrr解决方案。

library(tidyverse)
library(broom)

models <- list(hp ~ exp(cyl), hp ~ cyl)

mtcars %>% 
    list %>%                         # make it a list
    cross2(models) %>%               # get combinations
    transpose %>%                    # put into a nice format
    set_names("data", "formula") %>% # set names to lm arg names
    pmap(lm) %>%                     # fit models
    map_df(tidy)                     # tidy it up
于 2018-02-05T18:21:34.087 回答
0

这与工作方式有点不一致purrr::map。您正在映射模型列表(一次列表中的一项),而不是数据框(一次将是数据框的一列)。因为即使使用其他模型表达式,数据框也保持不变,我认为映射不适用于这种情况。

但是,您可以通过根据上面的定义自定义函数来获得所需的语法。

library(tidyverse)
library(broom)
models <- list(hp ~ exp(cyl), hp ~ cyl)

models_to_rows <- function(data, models_list) {
  models_list %>%
    map_df(~tidy(lm(data=data, formula=.x)))
}

mtcars %>%
  models_to_rows(models)
#>          term     estimate    std.error statistic      p.value
#> 1 (Intercept)  89.60052274  9.702303069  9.234975 2.823542e-10
#> 2    exp(cyl)   0.04045315  0.004897717  8.259594 3.212750e-09
#> 3 (Intercept) -51.05436157 24.981944312 -2.043650 4.985522e-02
#> 4         cyl  31.95828066  3.883803355  8.228604 3.477861e-09
于 2018-02-04T21:51:57.190 回答