如何无需逐个构建mgcv::gam模型,获取ggplot2中geom_smooth(gam)每条拟合线的调整R²?
解决思路
1. 分组批量拟合自动处理(最推荐)
既然你是按分组生成多条GAM拟合线,完全不用手动逐个敲model1 <- gam(...)这种重复代码,用dplyr的分组映射工具就能自动遍历每个分组、拟合模型并提取统计量。
举个具体的例子,假设你的数据框df包含响应变量y、自变量x1和分组变量group:
library(tidyverse) library(mgcv) # 批量拟合GAM并计算调整R² group_adj_r2 <- df %>% group_by(group) %>% group_map(~ { # 对当前分组拟合GAM模型 gam_mod <- gam(y ~ s(x1), data = .x) # 获取基础R²和GAM的有效自由度(不能用普通线性模型的参数个数) base_r2 <- summary(gam_mod)$r.sq n <- nrow(.x) total_edf <- sum(summary(gam_mod)$edf) # 计算适配GAM的调整R² adj_r2 <- 1 - (1 - base_r2) * (n - 1) / (n - total_edf - 1) # 返回当前分组的结果 tibble(group = .y$group, adj_r_squared = adj_r2) }) %>% bind_rows()
跑完这段代码就能得到每个分组对应的调整R平方,就算有几十上百个分组也不用手动重复操作。如果你的GAM公式更复杂(比如加多个光滑项或协变量),直接修改gam()里的公式即可,所有分组会自动套用。
2. 结合broom包简化统计量提取
要是想更优雅地整理模型结果,可以搭配broom包,它能把模型输出转换成整洁的数据框,让统计量提取更顺畅:
library(broom) gam_stats <- df %>% group_by(group) %>% group_map(~ { gam_mod <- gam(y ~ s(x1), data = .x) # 用glance提取基础模型统计量(含R²、AIC等) mod_glance <- glance(gam_mod) # 计算调整R² n <- nrow(.x) total_edf <- sum(summary(gam_mod)$edf) adj_r2 <- 1 - (1 - mod_glance$r.squared) * (n - 1) / (n - total_edf - 1) # 合并结果并补充分组信息 mod_glance %>% mutate(group = .y$group, adj_r_squared = adj_r2) }) %>% bind_rows()
除了调整R平方,glance还会返回AIC、BIC等其他常用统计量,需要的话可以直接取用。
3. 从已生成的ggplot对象提取?(不推荐)
如果你已经用ggplot2的geom_smooth(method = "gam")画出了图,理论上可以通过ggplot_build()提取图层的计算数据,但这里面只有拟合值,没有完整的GAM模型对象,没法直接计算调整R平方。所以这种方法远不如直接批量拟合模型靠谱——毕竟ggplot的核心是绘图,不是保存模型参数。
最后提醒一句:GAM的调整R平方计算必须用有效自由度(edf),不能套用普通线性模型的调整R平方公式,上面的代码已经适配了这一点,可以放心用。
内容的提问来源于stack exchange,提问作者George
相关产品推荐
相关产品推荐

