如何在R语言时间序列图中添加loess拟合线?
解决R语言时间序列中添加loess拟合线的问题
别担心,我来帮你理清loess函数的公式参数,还会教你添加两条不同span的拟合线,一步步来:
核心知识点:loess的公式格式
loess函数的公式遵循因变量 ~ 自变量的格式,这里我们要拟合生猪屠宰数量随时间的变化趋势,所以:
- 因变量:就是你的屠宰数量列(示例里是
Total of Killed Pigs,真实数据里是那个长列名Monthly.total.number.of.pigs.slaughtered.in.Victoria..Jan.1980...August.1995) - 自变量:需要是连续的数值型时间变量(loess不能直接用字符型日期,所以我们可以生成一个时间索引,或者把日期转成数值)
先修正你的示例代码并实现拟合
你的示例数据里有个小错误:列名Monts拼写错了,应该是Months,先修正这个,然后添加时间索引,再拟合:
# 修正后的示例数据框(修正列名拼写) table <- structure( list( Months = c("1980-06", "1980-07", "1980-08", "1980-09", "1980-10", "1980-11", "1980-12", "1981-01"), `Total of Killed Pigs` = c(75000, 70000, 60000, 73000, 72000, 71000, 76000, 71000) ), row.names = c(NA, 8L), class = "data.frame" ) # 生成时间索引(连续数值,代表第几个时间点) table$time_idx <- 1:nrow(table) # 创建时间序列对象并绘图 ts.obj <- ts(table$`Total of Killed Pigs`, start = c(1980, 1), frequency = 12) plot(ts.obj, main = "生猪屠宰数量时间序列 + loess拟合", ylab = "屠宰数量") # 第一条loess拟合线(span=1,平滑度高) trend1 <- loess(`Total of Killed Pigs` ~ time_idx, data = table, span = 1) predict1 <- predict(trend1) lines(predict1, col = "blue", lwd = 2) # 第二条loess拟合线(span=0.5,更贴近原始数据) trend2 <- loess(`Total of Killed Pigs` ~ time_idx, data = table, span = 0.5) predict2 <- predict(trend2) lines(predict2, col = "red", lwd = 2) # 添加图例区分两条线 legend("topright", legend = c("span=1", "span=0.5"), col = c("blue", "red"), lwd = 2)
真实数据的完整代码
针对你下载的真实数据,代码逻辑是一样的,只需要调整列名:
# 读取数据(替换成你的文件路径) obj <- read.csv(file="PATH/monthly-total-number-of-pigs-sla.csv", header=TRUE, sep=",") # 生成时间索引 obj$time_idx <- 1:nrow(obj) # 创建时间序列对象并绘图 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 = "维多利亚州生猪屠宰数量时间序列", ylab = "月度屠宰数量") # 第一条loess拟合线(span=1) trend1 <- loess(Monthly.total.number.of.pigs.slaughtered.in.Victoria..Jan.1980...August.1995 ~ time_idx, data = obj, span = 1) predict1 <- predict(trend1) lines(predict1, col = "blue", lwd = 2) # 第二条loess拟合线(span=0.3,更灵敏捕捉波动) trend2 <- loess(Monthly.total.number.of.pigs.slaughtered.in.Victoria..Jan.1980...August.1995 ~ time_idx, data = obj, span = 0.3) predict2 <- predict(trend2) lines(predict2, col = "red", lwd = 2) # 添加图例 legend("topright", legend = c("span=1", "span=0.3"), col = c("blue", "red"), lwd = 2)
关键说明
span参数:控制拟合线的平滑程度,值越大线越平滑,值越小越贴近原始数据(通常在0.2到1之间调整)- 为什么用
time_idx而不是日期?因为loess要求自变量是数值型,直接用日期的话需要先转成数值(比如as.numeric(as.Date(obj$Months))),但用连续索引更简单直观,对时间序列趋势拟合的效果是一样的 - 如果列名有空格或特殊字符,记得用反引号
`把列名包起来,避免报错
内容的提问来源于stack exchange,提问作者Esinede1
相关产品推荐
相关产品推荐

