如何使用dplyr管道执行lm线性模型拟合并正确调用glance提取结果
报错原因
你遇到的报错本质是传参类型错误:dplyr::do()返回的是包含模型列表列的tibble对象,你直接把整个tibble传给glance()时,函数找不到针对tibble类的处理方法,自然会抛出错误。glance()接收的输入应该是lm类的模型对象,不是存储模型的tibble。
可复现的正确写法
以下几种管道写法都能得到和非管道写法完全一致的模型统计结果,你可以根据使用场景选择:
- 单模型最简写法(不需要留存模型对象时首选)
不需要嵌套操作,直接把管道里拟合的模型传给glance()即可:
library(broom) library(tidyverse) dat <- structure(list(x = c(800, 400, 200, 100, 50), y = c(605, 467, 323, 219, 110)), row.names = c(NA, -5L), class = c("tbl_df", "tbl", "data.frame")) # 管道直接拟合+提取统计量 dat %>% lm(y ~ x, data = .) %>% glance()
- 沿用
do()语法的修正写法
如果要保留do()的使用习惯,只需要从生成的tibble中取出模型对象,再传给glance():
fit_conc_df <- dat %>% do(fit_conc = lm(y ~ x, data = .)) %>% summarise(glance(fit_conc[[1]]))
如果是配合group_by()分组拟合多个模型,只需要把fit_conc[[1]]替换为对列表列的批量映射即可,比如搭配purrr::map_dfr直接按行合并所有模型的统计量。
- 现行tidyverse推荐的标准化建模流程写法
目前更推荐用nest()+purrr::map()的范式做管道内建模,逻辑更清晰,后续拓展提取系数、批量预测也更方便:
fit_res <- dat %>% # 把所有数据嵌套为列表列 nest(input_data = everything()) %>% mutate( # 批量拟合模型 lm_model = map(input_data, ~lm(y ~ x, data = .x)), # 批量提取模型统计量 model_metrics = map(lm_model, glance) ) %>% # 解嵌套得到结构化的统计结果 unnest(model_metrics) %>% # 按需移除不需要的中间列 select(-input_data, -lm_model)
运行以上任意一种写法,都能得到包含r.squared、adj.r.squared、AIC、BIC等指标的标准统计结果,和你非管道写法的输出完全一致。
内容的提问来源于stack exchange,提问作者littleworth
相关产品推荐
相关产品推荐

