使用broom从分组线性模型提取斜率和R²时报错如何解决?
报错原因
你使用group_by() + do()生成的回归结果表all_regress仍然保留了LC作为分组变量的分组属性,后续执行mutate()时,运算逻辑会按组执行:每组内mod1是单个lm模型对象(而非多元素列表),map()会遍历lm对象本身的所有内部属性(包括qr类子属性),而broom没有对应qr类的tidy方法,因此抛出错误。
未分组时do()返回的是普通列表列tibble,map()会直接遍历mod1列的每个完整lm对象,因此可以正常运行。
修复方案
方案1:最简修改(仅新增一行解除分组)
在提取模型指标前先解除分组即可,修改后完整代码如下:
library(tidyverse) library(broom) # 读取数据集 data(mtcars) # 构造分组数据 mtcars <- mtcars %>% as_tibble() %>% mutate(LC = 1) mtcars2 <- mtcars %>% mutate(LC = 2) mtcars <- rbind(mtcars, mtcars2) # 分组建模 all_regress <- mtcars %>% group_by(LC) %>% do(mod1 = lm(mpg ~ disp, data = .), mod2 = lm(mpg ~ wt, data = .)) # 解除分组后再提取指标(仅新增这一行) all_regress <- all_regress %>% ungroup() # 提取斜率和R平方 glance <- all_regress %>% mutate(tidy = map(mod1, broom::tidy), glance = map(mod1, broom::glance), augment = map(mod1, broom::augment), rsq = glance %>% map_dbl('r.squared'), slope = tidy %>% map_dbl(function(x) x$estimate[2]))
方案2:更稳定的嵌套分组写法(推荐)
do()属于tidyverse中老旧语法,更推荐用nest_by()嵌套分组数据后建模,逻辑更清晰也不容易出问题:
library(tidyverse) library(broom) data(mtcars) mtcars <- mtcars %>% as_tibble() %>% mutate(LC = 1) mtcars2 <- mtcars %>% mutate(LC = 2) mtcars <- rbind(mtcars, mtcars2) # 嵌套分组+建模+提取指标一步完成 res <- mtcars %>% nest_by(LC) %>% mutate(mod1 = list(lm(mpg ~ disp, data = data)), # 直接提取斜率 slope = broom::tidy(mod1)$estimate[2], # 直接提取R平方 rsq = broom::glance(mod1)$r.squared) %>% # 可选:移除不需要的嵌套数据和模型列 select(LC, slope, rsq)
内容的提问来源于stack exchange,提问作者Stefano Potter
相关产品推荐
相关产品推荐

