7

我是purrr范式的新手,并且正在努力解决它。

根据几个来源,我已经设法嵌套数据框,在嵌套数据上运行线性模型,从每个 lm 中提取一些系数,并为每个 lm 生成摘要。我想做的最后一件事是从摘要中提取“r.squared”(我原以为这是我想要实现的最简单的部分),但无论出于何种原因,我都无法获得语法正确的。

这是我所拥有的 MWE:

library(purrr)
library(dplyr)
library(tidyr)

mtcars %>%
  nest(-cyl) %>%
  mutate(fit = map(data, ~lm(mpg ~ wt, data = .)),
         sum = map(fit, ~summary))

这是我提取失败的 r.squared 的尝试:

mtcars %>%
  nest(-cyl) %>%
  mutate(fit = map(data, ~lm(mpg ~ wt, data = .)),
         sum = map(fit, ~summary),
         rsq = map_dbl(sum, "r.squared"))
Error in eval(substitute(expr), envir, enclos) : 
  `x` must be a vector (not a closure)

这与 RStudio 网站上给出的示例表面上相似:

mtcars %>%
  split(.$cyl) %>%
  map(~ lm(mpg ~ wt, data = .x)) %>%
  map(summary) %>%
  map_dbl("r.squared")

这可行,但是我希望 r.squared 值位于一个新列中(因此是 mutate 语句),并且我想了解为什么我的代码不起作用而不是解决问题。

编辑:

这是我使用以下解决方案的工作解决方案:

mtcars %>%
      nest(-cyl) %>% 
      mutate(fit = map(data, ~lm(mpg ~ wt, data = .)),
             summary = map(fit, glance),
             r_sq = map_dbl(summary, "r.squared"))

编辑2:

因此,事实证明该错误来自于在 summary = map(fit, ~summary) 行中包含波浪号键。我的猜测是使对象成为嵌套的函数,而不是摘要本身返回的对象。如果有人想插话,希望对此有权威的回答。

需要明确的是,这个版本的原始代码可以正常工作:

mtcars %>%
  nest(-cyl) %>%
  mutate(fit = map(data, ~lm(mpg ~ wt, data = .)),
         summary = map(fit, summary),
         r_sq = map_dbl(summary, "r.squared"))
4

3 回答 3

6

为了适合您当前的管道,您需要与包unnest一起使用mapglancebroom包中使用。

library(tidyr)
library(dplyr)
library(broom)

mtcars %>%
  nest(-cyl) %>%
  mutate(fit = map(data, ~lm(mpg ~ wt, data = .))) %>% 
  unnest(map(fit, glance))

您将获得的不仅仅是 r-squared,而且您可以从那里select删除不需要的东西。

如果要将模型摘要嵌套在列表列中:

mtcars %>%
  nest(-cyl) %>% 
  mutate(fit = map(data, ~lm(mpg ~ wt, data = .)),
         summary = map(fit, glance)) 

如果您只想从嵌套框架中提取单个值,您只需要使用map实际值(而不是[[extract2如我最初建议的那样,非常感谢您发现这一点)。

mtcars %>%
  nest(-cyl) %>% 
  mutate(fit = map(data, ~lm(mpg ~ wt, data = .)),
         summary = map(fit, glance),
         r_sq = map_dbl(summary, "r.squared"))
于 2016-12-02T13:33:41.197 回答
5

我认为对于您想要实现的目标,您最好使用包中的glance()功能broom

library(broom)
library(dplyr)
mtcars %>%
  group_by(cyl) %>%
  do(glance(lm(mpg ~ wt, data = .))) %>%
  select(cyl, r.squared)
#    cyl r.squared
#  <dbl>     <dbl>
#1     4 0.5086326
#2     6 0.4645102
#3     8 0.4229655
于 2016-12-02T10:59:34.303 回答
1

必须有更好的方法,这是我对管道的尝试:

mtcars %>%
  split(.$cyl) %>%
  map(~ lm(mpg ~ wt, data = .x)) %>%
  map(summary) %>%
  map_dbl("r.squared") %>% 
  list() %>% 
  as.data.frame(col.names = "r.squared") %>% 
  add_rownames(var = "cyl")

# # A tibble: 3 × 2
#     cyl r.squared
#   <chr>     <dbl>
# 1     4 0.5086326
# 2     6 0.4645102
# 3     8 0.4229655

注意:您可能会收到以下警告。

警告消息:已弃用,请改用 tibble::rownames_to_column()。

于 2016-12-02T11:27:10.200 回答