ggplot2中为geom_smooth()指定自定义置信区间及分组实现
自定义geom_smooth置信区间上下限实现方案
核心逻辑
geom_smooth()本身不支持直接传入自定义值替换默认计算的标准误置信区间,要实现自定义上下限的平滑填充带,搭配geom_ribbon()即可完成:先对上下限变量做与平滑线同参数的非参数拟合,再将拟合值作为ymin/ymax传入geom_ribbon()绘制填充层,最后叠加关闭默认se的geom_smooth()线条即可。
单组数据实现
参考代码如下,效果与默认geom_smooth()结构完全一致,仅填充区间替换为自定义的高低温平滑范围:
library(ggplot2) set.seed(123) mean_temp <- runif(365, min = 10, max = 25) max_temp <- runif(365, min = 26, max = 35) min_temp <- runif(365, min = 0, max = 9) temp <- data.frame(day = 1:365, mean = mean_temp, max = max_temp, min = min_temp) # 提前拟合高低温的平滑值,loess参数与geom_smooth默认保持一致 temp$smooth_low <- predict(loess(min ~ day, data = temp, span = 0.75)) temp$smooth_high <- predict(loess(max ~ day, data = temp, span = 0.75)) ggplot(temp, aes(x = day, y = mean)) + geom_ribbon(aes(ymin = smooth_low, ymax = smooth_high), alpha = 0.2, fill = "grey50") + geom_smooth(se = FALSE, color = "#2166ac", linewidth = 1)
注意:不建议直接使用min/max这类R内置函数名作为变量名,容易触发函数调用冲突。
多分组数据问题修复
原有代码填充带无法按分组匹配的两个核心原因:
- 仅用
group_by()给数据打分组标签时,在aes()内部直接调用predict(loess(...))不会自动按分组建模,会使用全量数据拟合出一套全局上下限,所有分组共用 geom_ribbon()需要映射fill美学与分组变量绑定,仅映射color无法生成独立的分组填充区域,还会出现多余的填充带边框
修复后可正常生成各分组独立的平滑线+匹配填充带:
library(tidyverse) set.seed(123) # 构造示例数据 temp <- rbind( data.frame(day = 1:365, mean = runif(365, 10, 25), max = runif(365, 26, 35), min = runif(365, 0, 9), label = 'A'), data.frame(day = 1:365, mean = runif(365, 10, 25), max = runif(365, 200, 220), min = runif(365, -10, 9), label = 'B'), data.frame(day = 1:365, mean = runif(365, 10, 25), max = runif(365, 30, 40), min = runif(365, -5, 5), label = 'C') ) # 按分组分别拟合高低温平滑值 temp <- temp %>% group_by(label) %>% group_modify(~{ .x$smooth_low <- predict(loess(min ~ day, data = .x, span = 0.75)) .x$smooth_high <- predict(loess(max ~ day, data = .x, span = 0.75)) .x }) %>% ungroup() # 绘图 ggplot(temp, aes(x = day, y = mean, color = label, fill = label)) + geom_ribbon(aes(ymin = smooth_low, ymax = smooth_high), alpha = 0.1, color = NA) + geom_smooth(se = FALSE, linewidth = 1)
绘制注意事项
- 图层顺序遵循“先下层后上层”:
geom_ribbon()要放在geom_smooth()之前调用,避免填充带遮挡平滑线 - 拟合上下限的模型参数(如loess的span值)要与
geom_smooth()使用的参数保持一致,避免填充带与中间曲线的平滑度不匹配 - 多分组场景下
geom_ribbon()设置color = NA可以去掉填充区域的外边框,视觉效果与默认geom_smooth(se=TRUE)的样式完全统一
内容的提问来源于stack exchange,提问作者tamarack
相关产品推荐
相关产品推荐

