求助:geom_smooth未呈现预期水平曲线(不愿调整span)
解决geom_smooth在常数数据下的边缘峰值问题
问题原因
你遇到的是loess局部加权回归的边缘效应:当第一个数据点与后续点间隔较大时,局部回归在边缘区域的权重分配会导致拟合曲线偏离真实值,出现异常峰值。由于你不想调整span参数(会影响其他数据的拟合效果),可以通过以下两种针对性方案解决:
方案一:自定义平滑逻辑,动态切换拟合方法
通过自定义函数判断每组数据的y值是否为常数,常数数据用线性回归拟合水平线,非常数数据保留默认loess方法:
# 自定义平滑方法 custom_smooth <- function(formula, data, ...) { if (length(unique(data$y)) == 1) { # 常数数据拟合水平线 lm(formula, data = data, ...) } else { # 非常数数据使用默认loess loess(formula, data = data, ...) } } # 修改后的绘图代码 ggplot(test, aes(month_day, Sensibilite, label = Nom, color = Nom)) + geom_smooth(method = custom_smooth, se = FALSE, size=0.5) + geom_point(size =0.5)+ geom_label_repel(aes(label = after_stat(helper_label(x, color, PANEL, "max"))), stat = "smooth", method = custom_smooth, # 同步指定自定义方法 segment.size = 0.1, max.overlaps = Inf, size = 2, na.rm = TRUE, direction = "y", nudge_x = 30 ) + theme_light()+ theme(legend.position = "none")+ scale_y_continuous(limits = c(0,6))+ scale_x_date(expand = c(0.15, 0),name = "Mois",date_breaks = "1 month",date_labels = "%b")
方案二:调整loess的边界控制参数
无需切换方法,仅修改loess的surface参数为"direct",限制拟合范围在数据点区间内,避免边缘外推:
ggplot(test, aes(month_day, Sensibilite, label = Nom, color = Nom)) + geom_smooth(method = "loess", method.args = list(control = loess.control(surface = "direct")), se = FALSE, size=0.5) + geom_point(size =0.5)+ geom_label_repel(aes(label = after_stat(helper_label(x, color, PANEL, "max"))), stat = "smooth", method = "loess", method.args = list(control = loess.control(surface = "direct")), segment.size = 0.1, max.overlaps = Inf, size = 2, na.rm = TRUE, direction = "y", nudge_x = 30 ) + theme_light()+ theme(legend.position = "none")+ scale_y_continuous(limits = c(0,6))+ scale_x_date(expand = c(0.15, 0),name = "Mois",date_breaks = "1 month",date_labels = "%b")
效果说明
两种方案都能让常数数据的拟合曲线保持水平线,同时完全保留原span参数对其他非常数数据的拟合效果。
内容的提问来源于stack exchange,提问作者Mmerose
相关产品推荐
相关产品推荐

