You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在R语言中为时间序列绘制多项式回归线?

解决美国新冠日增病例的三次多项式拟合绘图问题

嘿,别纠结lm()函数的适用性啦!你只是想给日增病例散点图加一条三次趋势曲线,这种场景下**lm()完全够用**——ARIMA这类时间序列模型是用来处理自相关结构、做预测的,而你现在的需求是拟合多项式趋势,普通线性回归就能搞定。

我帮你调整了代码,既保留了你原来的绘图样式,又加入了三次拟合曲线的绘制步骤:

options(repr.plot.width=14, repr.plot.height=10)
# 安装并加载所需包
install.packages('RCurl')
require(repr)
require(RCurl)
require(tidyverse)

# 提取并整理约翰霍普金斯的新冠确诊数据
x = getURL("https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv")
corona <- read_csv(x) %>%
  pivot_longer(cols = -c(`Province/State`, `Country/Region`, Lat, Long), 
               names_to = "date", values_to = "cases") %>%
  select(`Province/State`, `Country/Region`, date, cases) %>%
  mutate(date = as.Date(date, format = "%m/%d/%y")) %>%
  drop_na(cases) %>%
  rename(country = "Country/Region", provinces = "Province/State")

# 筛选美国数据,计算日增病例
cc <- corona %>% filter(country == "US")
ccw <- cc %>% 
  pivot_wider(names_from = "country", values_from = "cases") %>%
  filter(US > 5)

# 整理日增病例与对应日期(diff后长度减1,需对齐日期)
first.der <- diff(ccw$US, lag = 1, differences = 1)
plot_data <- tibble(
  date = ccw$date[-1],  # 去掉第一个日期,和日增数据匹配
  daily_cases = first.der
)

# 拟合三次多项式回归:将日期转为数值型(天数)作为自变量
# raw=TRUE使用原始多项式项,更贴合我们对三次曲线的直观理解
poly_model <- lm(daily_cases ~ poly(as.numeric(date), 3, raw = TRUE), data = plot_data)

# 生成拟合值
plot_data$fit <- predict(poly_model)

# 绘制散点图(保留你原有的样式)
plot(plot_data$date, plot_data$daily_cases, 
     pch = 19, cex = 1.2, ylab = '', xlab = '', 
     main = 'Daily COVID-19 cases in US', col = "firebrick", 
     axes = FALSE, cex.main = 1.5)
abline(h = 0)
abline(v = max(plot_data$date), col = 'gray90')
abline(h = plot_data$daily_cases[nrow(plot_data)], col = 'firebrick', lty = 2, lwd = .5)

# 添加日期轴和Y轴
at1 <- seq(min(plot_data$date), max(plot_data$date), by = 2)
axis.Date(1, at = at1, format = "%b %d", las = 2, cex.axis = 0.7)
axis(side = 2, seq(min(plot_data$daily_cases), max(plot_data$daily_cases), 1000), 
     las = 2, cex.axis = 1)

# 叠加三次拟合曲线
lines(plot_data$date, plot_data$fit, col = "navy", lwd = 2)
# 添加图例说明
legend("topright", legend = c("Daily Cases", "3rd Degree Polynomial Fit"),
       col = c("firebrick", "navy"), pch = c(19, NA), lty = c(NA, 1), lwd = 2, cex = 1.2)

关键细节解释:

  • 为什么能用lm():你要的是拟合一条描述数据趋势的曲线,属于回归拟合范畴,和时间序列的“预测建模”是两回事。只要不需要捕捉数据的自相关特性(比如ARIMA的核心功能),lm()完全能胜任这个可视化需求。
  • 日期转数值lm()无法直接处理Date类型的自变量,所以用as.numeric(date)把日期转换成从1970-01-01开始的天数,作为多项式回归的输入。
  • poly(..., raw=TRUE):如果不加这个参数,R会默认生成正交多项式,拟合的趋势是一样的,但系数的解释性会变差;我们只需要画曲线,用原始多项式更直观。

如果之后发现残差存在自相关(日增病例的前后值有明显关联),可以考虑用nlme包的gls()函数加入自相关结构,但对于单纯的趋势可视化来说,上面的代码已经完全满足需求啦!

内容的提问来源于stack exchange,提问作者Antoni Parellada

火山引擎 最新活动