本文目录导读:

我来为你详细介绍使用Pandas进行数据平滑的几种常用方法,并给出完整案例。
数据平滑的常用方法
移动平均法
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 创建示例数据(带噪声的正弦波)
np.random.seed(42)
t = np.linspace(0, 10, 100)
data = np.sin(t) + np.random.normal(0, 0.3, 100)
df = pd.DataFrame({'time': t, 'value': data})
# 移动平均平滑
df['sma_3'] = df['value'].rolling(window=3, center=True).mean() # 3点移动平均
df['sma_5'] = df['value'].rolling(window=5, center=True).mean() # 5点移动平均
df['sma_10'] = df['value'].rolling(window=10, center=True).mean() # 10点移动平均
# 可视化
plt.figure(figsize=(12, 6))
plt.plot(df['time'], df['value'], 'o-', label='原始数据', alpha=0.5)
plt.plot(df['time'], df['sma_3'], label='3点移动平均', linewidth=2)
plt.plot(df['time'], df['sma_5'], label='5点移动平均', linewidth=2)
plt.plot(df['time'], df['sma_10'], label='10点移动平均', linewidth=2)
plt.legend()'移动平均平滑效果对比')
plt.grid(True, alpha=0.3)
plt.show()
指数加权移动平均
# 指数加权移动平均(对近期数据给予更高权重) df['ewm_01'] = df['value'].ewm(alpha=0.1, adjust=False).mean() # 平滑系数0.1 df['ewm_03'] = df['value'].ewm(alpha=0.3, adjust=False).mean() # 平滑系数0.3 df['ewm_05'] = df['value'].ewm(alpha=0.5, adjust=False).mean() # 平滑系数0.5 # 可视化 plt.figure(figsize=(12, 6)) plt.plot(df['time'], df['value'], 'o-', label='原始数据', alpha=0.5) plt.plot(df['time'], df['ewm_01'], label='alpha=0.1', linewidth=2) plt.plot(df['time'], df['ewm_03'], label='alpha=0.3', linewidth=2) plt.plot(df['time'], df['ewm_05'], label='alpha=0.5', linewidth=2) plt.legend()'指数加权移动平均平滑效果对比') plt.grid(True, alpha=0.3) plt.show()
中值滤波
# 中值滤波(对异常值具有很好的鲁棒性) df['median_3'] = df['value'].rolling(window=3, center=True).median() df['median_5'] = df['value'].rolling(window=5, center=True).median() # 可视化 plt.figure(figsize=(12, 6)) plt.plot(df['time'], df['value'], 'o-', label='原始数据', alpha=0.5) plt.plot(df['time'], df['median_3'], label='3点中值滤波', linewidth=2) plt.plot(df['time'], df['median_5'], label='5点中值滤波', linewidth=2) plt.legend()'中值滤波平滑效果对比') plt.grid(True, alpha=0.3) plt.show()
实战案例:股票价格平滑
# 模拟股票价格数据
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=100, freq='D')
price = 100 + np.cumsum(np.random.normal(0, 2, 100)) + np.random.normal(0, 1, 100)
stock_df = pd.DataFrame({'date': dates, 'price': price})
stock_df.set_index('date', inplace=True)
# 多种平滑方法
stock_df['SMA_5'] = stock_df['price'].rolling(window=5).mean()
stock_df['SMA_10'] = stock_df['price'].rolling(window=10).mean()
stock_df['EWMA'] = stock_df['price'].ewm(span=10, adjust=False).mean()
stock_df['HMA'] = stock_df['price'].rolling(window=10).mean().rolling(window=5).mean()
# 可视化
plt.figure(figsize=(14, 7))
plt.plot(stock_df['price'], label='原始价格', alpha=0.6, linewidth=1)
plt.plot(stock_df['SMA_5'], label='5日移动平均', linewidth=2)
plt.plot(stock_df['SMA_10'], label='10日移动平均', linewidth=2)
plt.plot(stock_df['EWMA'], label='指数加权平均(span=10)', linewidth=2, linestyle='--')
plt.plot(stock_df['HMA'], label='双移动平均', linewidth=2, linestyle=':')
plt.legend(loc='best')'股票价格平滑分析')
plt.xlabel('日期')
plt.ylabel('价格')
plt.xticks(rotation=45)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
批量处理多个数据列
# 创建多列数据
multi_df = pd.DataFrame({
'A': np.sin(np.linspace(0, 10, 100)) + np.random.normal(0, 0.2, 100),
'B': np.cos(np.linspace(0, 10, 100)) + np.random.normal(0, 0.2, 100),
'C': np.sin(np.linspace(0, 10, 100)) * 2 + np.random.normal(0, 0.2, 100)
})
def smooth_data(df, window=5, method='mean'):
"""批量平滑数据的函数"""
if method == 'mean':
return df.rolling(window=window, center=True).mean()
elif method == 'median':
return df.rolling(window=window, center=True).median()
elif method == 'ewm':
return df.ewm(span=window, adjust=False).mean()
# 应用平滑
window = 5
smooth_mean = smooth_data(multi_df, window, 'mean')
smooth_median = smooth_data(multi_df, window, 'median')
smooth_ewm = smooth_data(multi_df, window, 'ewm')
# 可视化
fig, axes = plt.subplots(3, 1, figsize=(12, 10))
for i, col in enumerate(multi_df.columns):
axes[i].plot(multi_df[col], 'o-', label='原始数据', alpha=0.5, markersize=3)
axes[i].plot(smooth_mean[col], label=f'{window}点移动平均', linewidth=2)
axes[i].plot(smooth_median[col], label=f'{window}点中值滤波', linewidth=2)
axes[i].plot(smooth_ewm[col], label=f'EWM(span={window})', linewidth=2, linestyle='--')
axes[i].set_title(f'列 {col}')
axes[i].legend()
axes[i].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
平滑效果评估
# 评估平滑效果
def evaluate_smoothing(original, smoothed, name):
"""评估平滑效果"""
# 计算平滑前后的变化
original_variance = original.var()
smoothed_variance = smoothed.var()
reduction = (1 - smoothed_variance / original_variance) * 100
# 计算均方误差(MSE)
mse = ((original - smoothed) ** 2).mean()
return {
'方法': name,
'原始方差': f'{original_variance:.4f}',
'平滑后方差': f'{smoothed_variance:.4f}',
'方差减少(%)': f'{reduction:.2f}%',
'MSE': f'{mse:.4f}'
}
# 评估不同平滑方法
results = []
for col in ['value']:
results.append(evaluate_smoothing(
df[col].dropna(),
df['sma_5'].dropna(),
'5点移动平均'
))
results.append(evaluate_smoothing(
df[col].dropna(),
df['ewm_03'].dropna(),
'指数平滑(alpha=0.3)'
))
results.append(evaluate_smoothing(
df[col].dropna(),
df['median_5'].dropna(),
'5点中值滤波'
))
# 创建评估结果DataFrame
evaluation_df = pd.DataFrame(results)
print("平滑效果评估:")
print(evaluation_df.to_string(index=False))
选择平滑方法的建议
- 移动平均:适用平稳序列,计算简单
- 指数加权移动平均:需要更多关注近期数据时使用
- 中值滤波:数据有较多异常值时效果最好
- 组合方法:可以先用中值滤波去异常,再用移动平均平滑
根据你的具体数据和需求选择合适的方法,通常需要尝试不同的窗口大小和参数来得到最佳效果。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播