如何为Month2分组应用geom_smooth拟合GAM样条曲线?
解决ggplot按分组拟合GAM样条曲线的问题
数据集结构
> str(env) tibble [1,363 × 15] (S3: tbl_df/tbl/data.frame) $ use_for_analysis: chr [1:1363] "Standard" "Standard" "Standard" "Standard" ... $ Date : POSIXct[1:1363], format: "2011-01-07" "2011-01-07" "2011-01-07" ... $ CYR : Factor w/ 18 levels "2005","2006",..: 7 7 7 5 7 7 7 7 7 5 ... $ Season : Factor w/ 2 levels "DRY","WET": 1 1 1 1 1 1 1 1 1 1 ... $ Month : num [1:1363] 1 1 1 1 1 1 1 1 1 1 ... $ Time : POSIXct[1:1363], format: "1899-12-31 10:05:00" "1899-12-31 10:38:00" "1899-12-31 10:55:00" ... $ time2 : POSIXct[1:1363], format: "2022-12-01 10:05:00" "2022-12-01 10:38:00" "2022-12-01 10:55:00" ... $ DT : POSIXct[1:1363], format: "2011-01-07 10:05:00" "2011-01-07 10:38:00" "2011-01-07 10:55:00" ... $ Site : Factor w/ 47 levels "1","2","3","4",..: 46 44 43 22 45 47 42 33 34 19 ... $ temp : num [1:1363] 17.6 18.4 18.6 18.8 18.8 ... $ sal : num [1:1363] 31.2 30.3 29.9 18.5 31.3 ... $ DO : num [1:1363] 6.12 6.65 6.29 6.56 7.25 ... $ water_depth : num [1:1363] 39 42 58 36 58 70 68 71 40 67 ... $ sed_depth : num [1:1363] 31 143 89 28 111 31 123 29 42 2 ... $ Month2 : Factor w/ 8 levels "Jan","Feb","Mar",..: 1 1 1 1 1 1 1 1 1 1 ...
问题场景
已通过ggplot绘制按Month2分组着色、CYR分面的temp随time2的散点图,尝试用geom_smooth(method='gam')为每个Month2分组拟合GAM样条曲线,但原代码无法实现,核心问题是geom_smooth的公式错误:
ggplot(env, aes(x=time2, y=temp, color = Month2)) + geom_point(alpha = 0.2) + geom_smooth(method='gam', formula = y ~ splines::ns(x,2) + b, se=FALSE) + # 此处公式中的b为无效变量 facet_wrap(~CYR)
解决方案
核心问题说明
原公式中的b没有对应数据集中的实际变量,且未正确利用ggplot的分组逻辑。要实现每个Month2分组单独拟合曲线,可通过以下两种方法调整:
方法1:利用ggplot自动分组(推荐)
因为aes中已设置color=Month2,ggplot会自动按该变量分组拟合曲线,只需将公式改为GAM适配的平滑项格式。优先使用mgcv包的s()函数(GAM标准平滑项),需先加载mgcv包:
library(mgcv) ggplot(env, aes(x=time2, y=temp, color = Month2)) + geom_point(alpha = 0.2) + geom_smooth(method = 'gam', formula = y ~ s(x, k=2), se = FALSE) + # s(x)为mgcv平滑项,k指定自由度 facet_wrap(~CYR)
若坚持使用splines::ns,需明确结合分组变量构建交互项:
ggplot(env, aes(x=time2, y=temp, color = Month2)) + geom_point(alpha = 0.2) + geom_smooth(method = 'gam', formula = y ~ splines::ns(x, 2) * Month2, se = FALSE) + facet_wrap(~CYR)
方法2:显式指定分组
若自动分组未生效,可在geom_smooth的aes中额外指定group=Month2,确保按分组拟合:
library(mgcv) ggplot(env, aes(x=time2, y=temp, color = Month2)) + geom_point(alpha = 0.2) + geom_smooth(aes(group=Month2), method='gam', formula = y ~ s(x, k=2), se=FALSE) + facet_wrap(~CYR)
关键提示
- 使用
method='gam'时,mgcv包的s()平滑项比splines::ns更适配GAM模型,是官方推荐用法。 - 无需在公式中额外写分组变量,
color=Month2或group=Month2已让ggplot为每个分组单独拟合曲线。
内容的提问来源于stack exchange,提问作者Nate
相关产品推荐
相关产品推荐

