如何在R中为时间序列绘制上下平滑曲线?
给LOESS趋势线添加残差平滑上下包络线
嘿,我懂你要的效果了——不是调整LOESS的span参数,而是基于主LOESS曲线的残差,画出平滑的上下边界包络线对吧?下面是用基础R就能实现的简便方法,完全贴合你现有的代码逻辑:
第一步:先搞定主LOESS趋势和残差
先拟合你选定的那条主LOESS曲线,然后算出每个数据点和拟合值之间的残差:
# 用你的完整数据集代码为例 obj <- read.csv(file="PATH/monthly-total-number-of-pigs-sla.csv", header=TRUE, sep=",") ts.obj <- ts(obj$Monthly.total.number.of.pigs.slaughtered.in.Victoria..Jan.1980...August.1995, start = c(1980, 1), frequency = 12) # 先画出原始时间序列 plot(ts.obj, main = "Monthly Slaughtered Pigs: LOESS Trend + Residual Envelopes", col = "gray") # 提取时间变量,方便后续拟合 time_vals <- as.numeric(time(ts.obj)) # 拟合主LOESS趋势(比如你用span=1的这条) trend_main <- loess(ts.obj ~ time_vals, data = obj, span = 1) fit_main <- predict(trend_main) # 画出主LOESS曲线 lines(time_vals, fit_main, col = "darkblue", lwd = 2) # 计算残差:原始值 - 拟合值 residuals <- ts.obj - fit_main
第二步:拟合残差的平滑上下边界
接下来,我们分别对正残差和负残差做LOESS平滑,这样就能得到贴合残差波动的上下包络线:
# 处理上边界:只保留正残差,再做LOESS平滑 upper_resid <- pmax(residuals, 0) trend_upper <- loess(upper_resid ~ time_vals, span = 0.3) # 这里的span控制平滑度,可按需调整 fit_upper <- fit_main + predict(trend_upper) # 处理下边界:只保留负残差,再做LOESS平滑 lower_resid <- pmin(residuals, 0) trend_lower <- loess(lower_resid ~ time_vals, span = 0.3) fit_lower <- fit_main + predict(trend_lower)
第三步:画出上下包络线
最后把这两条平滑边界加到图上就行:
# 用虚线画出上下边界,和主LOESS曲线同色系 lines(time_vals, fit_upper, col = "darkblue", lty = 2) lines(time_vals, fit_lower, col = "darkblue", lty = 2)
小提示
- 残差LOESS的
span参数是关键:值越大,包络线越平缓;值越小,越贴近残差的实际波动,你可以根据想要的效果微调。 - 如果习惯用
ggplot2,也可以用geom_smooth结合残差数据来实现,但上面的方法完全适配你现在用的基础绘图体系,不需要额外包。
内容的提问来源于stack exchange,提问作者Esinede1
相关产品推荐
相关产品推荐

