You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ggplot中平滑折线?附代码与数据求助

问题描述

我想重现一张折线图,但需要让折线更平滑,目标是做出接近平滑曲线的效果。目前我写了代码,但只得到了趋势线,没能把两个数据系列都做平滑处理。

我的现有代码:

plot_fig4 <- ggplot(fig4, aes(x=dias))+
  geom_line(aes(y=complete_preds_means), color="#9a6584", size=0.5)+
  geom_line(aes(y=contrafact), colour="#000000", size=0.5) + 
  geom_line(aes(y=complete_preds_means), method = "lm", formula=y~spline(x,21))+
  geom_ribbon(aes(ymin=complete_preds_lower, ymax=complete_preds_upper), fill="#9a6584", alpha=0.2)

我的数据:

structure(list(dias = structure(c(19052, 19053, 19054, 19055, 
19056, 19057, 19058, 19059, 19060, 19061, 19062, 19063, 19064, 
19065, 19066, 19067, 19068, 19069, 19070, 19071), class = "Date"), 
    complete_preds_means = c(341.07434, 381.59167, 455.47815, 
    485.05597, 527.60876, 562.63965, 602.48975, 624.663, 626.5637, 
    527.2239, 420.71643, 389.30804, 378.74396, 366.61548, 361.36566, 
    363.37253, 319.31824, 314.39688, 303.60342, 294.8934), contrafact = c(364.5, 
    358.89, 466.64, 470.11, 464.25, 487.27, 591.2, 715.33, 628.02, 
    505.98, 402.9, 316.81, 323.35, 358.61, 354.26, 369.5, 317.01, 
    336.5, 285.33, 270.91), complete_preds_lower = c(320.6368042, 
    361.7870895, 432.4487762, 461.2275833, 503.2255051, 535.7108551, 
    576.3850006, 597.9762146, 601.4407013, 504.0448837, 398.7777023, 
    368.0046799, 356.3603165, 345.5847885, 339.9679932, 342.7514801, 
    298.3247482, 293.4419693, 282.5286865, 275.4635284), complete_preds_upper = c(359.9897186, 
    402.5708664, 477.4746765, 508.7775711, 550.3326447, 587.6521027, 
    628.5320251, 649.9691833, 649.4831665, 547.9886108, 442.046402, 
    410.8121475, 399.0208908, 389.8615128, 387.4929993, 386.2935928, 
    340.140834, 336.3622116, 324.793483, 315.4606934)), row.names = c(NA, 
-20L), class = c("tbl_df", "tbl", "data.frame"))
解决方案

你之前的代码里用geom_line加method参数是无效的,geom_line不支持拟合方法。要实现平滑曲线,有两种常用方法:

方法1:用geom_smooth直接拟合

geom_smooth可以指定拟合方法,比如用广义可加模型(GAM)配合立方样条,能直接对两个数据系列做平滑处理:

library(ggplot2)
library(mgcv) # 依赖包,用于GAM拟合

plot_fig4 <- ggplot(fig4, aes(x = dias)) +
  # 平滑complete_preds_means系列
  geom_smooth(aes(y = complete_preds_means), color = "#9a6584", size = 0.5,
              method = "gam", formula = y ~ s(x, bs = "cs"), se = FALSE) +
  # 平滑contrafact系列
  geom_smooth(aes(y = contrafact), color = "#000000", size = 0.5,
              method = "gam", formula = y ~ s(x, bs = "cs"), se = FALSE) +
  # 保留原有的置信区间
  geom_ribbon(aes(ymin = complete_preds_lower, ymax = complete_preds_upper), 
              fill = "#9a6584", alpha = 0.2)

plot(plot_fig4)

方法2:手动用样条函数拟合后绘制

如果想更灵活控制平滑程度,可以先用smooth.spline手动拟合每个系列,再绘制拟合后的曲线:

# 拟合complete_preds_means的平滑曲线,df控制平滑度(值越小越平滑)
smooth_means <- smooth.spline(fig4$dias, fig4$complete_preds_means, df = 10)
smooth_means_df <- data.frame(dias = smooth_means$x, y_smooth = smooth_means$y)

# 拟合contrafact的平滑曲线
smooth_contra <- smooth.spline(fig4$dias, fig4$contrafact, df = 10)
smooth_contra_df <- data.frame(dias = smooth_contra$x, y_smooth = smooth_contra$y)

# 绘制图表
plot_fig4 <- ggplot() +
  geom_line(data = smooth_means_df, aes(x = dias, y = y_smooth), 
            color = "#9a6584", size = 0.5) +
  geom_line(data = smooth_contra_df, aes(x = dias, y = y_smooth), 
            color = "#000000", size = 0.5) +
  geom_ribbon(data = fig4, aes(x = dias, ymin = complete_preds_lower, ymax = complete_preds_upper), 
              fill = "#9a6584", alpha = 0.2)

plot(plot_fig4)

说明:

  • 方法1中的bs = "cs"是立方样条,能保证曲线连续平滑,适合时间序列数据。
  • 方法2中的df参数可调整平滑度:df越大,曲线越贴近原始数据;df越小,曲线越平滑。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 19:15:35