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

如何在时间序列图中添加平滑线?为各站点生成平滑曲线

嘿,我来给你几个实用的解决方案——不用先手动计算月度均值,直接在绘图环节就能让每个站点的时间序列曲线变得更平滑:

常用的绘图时自动平滑方法

1. 滑动窗口平滑(Rolling Window Smoothing)

这是最直观也最容易上手的方法,核心是对每个时间点取前后N个数据的均值/中位数,你可以根据数据的时间粒度灵活调整窗口大小(比如日数据用7天窗口,小时数据用24小时窗口)。

用Python的pandas+matplotlib实现的示例代码:

import pandas as pd
import matplotlib.pyplot as plt

# 假设你的数据存储在df中,包含'time'(时间列)、'value'(数值列)、'station'(站点列)
for station in df['station'].unique():
    # 取出单个站点的数据并按时间排序
    station_data = df[df['station'] == station].sort_values('time')
    # 计算7天中心滑动均值(center=True让窗口以当前点为中心)
    station_data['smoothed_value'] = station_data['value'].rolling(window=7, center=True).mean()
    # 绘制平滑后的曲线
    plt.plot(station_data['time'], station_data['smoothed_value'], label=f'{station} 平滑曲线')

plt.legend()
plt.xlabel('时间')
plt.ylabel('数值')
plt.show()

2. LOESS/LOWESS局部加权回归平滑

这种方法会对数据做局部加权拟合,能自适应捕捉数据的非线性波动,比滑动窗口更灵活,适合波动不规则的时间序列。

用seaborn可以一键实现,代码非常简洁:

import seaborn as sns
import matplotlib.pyplot as plt

# seaborn的lineplot自带lowess平滑选项,直接指定即可
sns.lineplot(data=df, x='time', y='value', hue='station', lowess=True)
plt.xlabel('时间')
plt.ylabel('数值')
plt.show()

如果需要更精细的控制,用statsmodels手动拟合:

from statsmodels.nonparametric.smoothers_lowess import lowess
import pandas as pd
import matplotlib.pyplot as plt

for station in df['station'].unique():
    station_data = df[df['station'] == station].sort_values('time')
    # frac参数控制平滑程度,取值0-1,越小越贴近原数据,越大越平滑
    smoothed_result = lowess(station_data['value'], station_data['time'], frac=0.15)
    # 提取平滑后的时间和数值
    smooth_time = smoothed_result[:, 0]
    smooth_value = smoothed_result[:, 1]
    plt.plot(smooth_time, smooth_value, label=f'{station} 平滑曲线')

plt.legend()
plt.xlabel('时间')
plt.ylabel('数值')
plt.show()

3. 三次样条插值平滑

如果你想要极致顺滑的曲线,可以用三次样条将离散的时间点连接成连续的平滑曲线,适合需要美观展示的场景。不过要注意,如果原数据存在异常值,可能会被过度拟合,建议先做异常值处理。

用scipy实现的示例:

from scipy.interpolate import make_interp_spline
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

for station in df['station'].unique():
    station_data = df[df['station'] == station].sort_values('time')
    # 将时间转换为数值格式(比如时间戳)
    time_num = np.array(station_data['time'].astype('int64'))
    values = station_data['value'].values
    # 创建三次样条插值函数
    spline_func = make_interp_spline(time_num, values, k=3)
    # 生成更密集的时间点,让曲线更顺滑
    smooth_time_num = np.linspace(time_num.min(), time_num.max(), 500)
    smooth_values = spline_func(smooth_time_num)
    # 转换回时间格式
    smooth_time = pd.to_datetime(smooth_time_num)
    plt.plot(smooth_time, smooth_values, label=f'{station} 平滑曲线')

plt.legend()
plt.xlabel('时间')
plt.ylabel('数值')
plt.show()

补充:R语言用户的方案

如果你用ggplot2绘图,直接用geom_smooth()函数就能轻松实现平滑:

library(ggplot2)
ggplot(df, aes(x = time, y = value, color = station)) +
  geom_line(alpha = 0.3) +  # 可选:绘制原曲线作为对比
  geom_smooth(method = "loess", se = FALSE) +  # LOESS平滑,se=FALSE去掉置信区间
  labs(x = "时间", y = "数值")

你可以根据自己数据的特点和需求选择合适的方法——滑动窗口适合简单场景,LOESS适合非线性波动数据,样条插值适合追求美观顺滑的展示~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:22:14