在使用loess拟合时,使用broom(增强)和dplyr时出现错误

4

我试图在一个loess拟合上使用增广,但是我收到以下错误:

Error in data.frame(..., check.names = FALSE) : 
  arguments imply differing number of rows: 32, 11

在错误信息中,11恰好等于一个段落中观察值的数量,而32是总观察值的数量。以下是代码。
require(broom)
require(dplyr)

# This example uses the lm method and it works
regressions <- mtcars %>% group_by(cyl) %>%  do(fit = lm(wt ~ mpg, .))
regressions %>% augment(fit)

# This example uses the loess method and it generates the error
regressions2 <- mtcars %>% group_by(cyl) %>%  do(fit = loess(wt ~ mpg, .))
regressions2 %>% augment(fit)

# The below code appropriately plots the loess fit using geom_smooth. 
# My current # workaround is to do a global definition as an aes object in geom_smooth`
cylc = unique(mtcars$cyl) %>% sort()
for (i in 1:length(cyl)){
  print(i)
  print(cyl[i])
  p<- ggplot(data=filter(mtcars,cyl==cylc[i]),aes(x=mpg,y=wt)) + geom_point() + geom_smooth(method="loess") + ggtitle(str_c("cyl = ",cyl[i]))
  print(p)
}
1个回答

11

这似乎是与do()运算符相关的问题:当我们检查 LOESS 模型对象之一上的 model.frame() 时,返回的不是相应模型的子集,而是所有32行。

解决方法是保留数据而不仅是模型,并将其作为第二个参数传递给 augment()

regressions2 <- mtcars %>%
  group_by(cyl) %>%
  do(fit = loess(wt ~ mpg, .),
     data = (.)) %>%
   augment(fit, data)

通常建议在使用augment()时进行如下操作,因为model.frame()无法获得所有原始列。


顺便说一句,我是broom的维护者,我一般不再推荐使用do()方法(因为dplyr已经大多数移动开了)。

相反,我建议使用tidyr的nest()和purrr的map(),如R4DS的这一章节所描述的,这使数据略微更容易管理并且能够加入到augment()之中。

library(tidyr)
library(purrr)

mtcars %>%
  nest(-cyl) %>%
  mutate(fit = map(data, ~ loess(wt ~ mpg, .))) %>%
  unnest(map2(fit, data, augment))

感谢David提供详细的回复。我已经阅读了那一章节,解决方案简明而明智。你可能需要考虑更新这里的vignette: https://cran.r-project.org/web/packages/broom/vignettes/broom_and_dplyr.html,因为这是我使用do()的起点。 - Steve
@Steve,你说得完全正确!有一些新的计划和资源来维护broom,这意味着这些更新很可能会在今年夏天发生。 - David Robinson
太棒了。再次感谢你的帮助! - Steve
作为可重复的解决方案,请添加库(tidyverse),库(broom)。 - Aran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接