如何为MultiIndex Series绘制带趋势线的图表?
解决MultiIndex分组数据添加趋势线的方法
核心思路
把MultiIndex转换成连续的时间序列索引,让工具能识别时间维度的连续性,进而拟合趋势线。
具体步骤
1. 将MultiIndex转换为DatetimeIndex
假设你的目标Series名为yes_freq,先把年和月组合成标准日期格式(比如每月第一天):
import pandas as pd # 从MultiIndex提取年、月,拼接为日期字符串后转成Datetime类型 dates = pd.to_datetime([f"{year}-{month}-01" for year, month in yes_freq.index]) # 重置索引为DatetimeIndex yes_freq = yes_freq.reset_index(drop=True).set_index(dates)
2. 绘制柱状图+趋势线
用Matplotlib实现
import matplotlib.pyplot as plt import numpy as np fig, ax = plt.subplots(figsize=(12,6)) # 绘制基础柱状图 yes_freq.plot(kind='bar', ax=ax, color='skyblue', label='Yes相对频率') # 把时间轴转为连续数值(用于拟合) x = np.arange(len(yes_freq)) y = yes_freq.values # 拟合线性趋势线(可调整多项式阶数实现非线性趋势) z = np.polyfit(x, y, 1) p = np.poly1d(z) # 绘制趋势线 ax.plot(x, p(x), color='red', linestyle='--', label=f'线性趋势: y={z[0]:.4f}x + {z[1]:.4f}') # 调整图表样式 ax.set_xlabel('年月') ax.set_ylabel('相对频率') ax.set_title('各年月Yes相对频率及趋势') ax.legend() plt.xticks(rotation=45) plt.tight_layout() plt.show()
用Seaborn实现
先把Series转为带辅助列的DataFrame,适配Seaborn的API:
import seaborn as sns # 转换为DataFrame并添加连续索引列 df = yes_freq.reset_index() df.columns = ['Date', 'Yes_Freq'] df['Seq'] = np.arange(len(df)) fig, ax = plt.subplots(figsize=(12,6)) # 绘制柱状图 sns.barplot(data=df, x='Date', y='Yes_Freq', ax=ax, color='skyblue') # 绘制趋势线(scatter=False只显示拟合线) sns.regplot(data=df, x='Seq', y='Yes_Freq', ax=ax, scatter=False, color='red', label='趋势线') # 调整样式 ax.set_xlabel('年月') ax.set_ylabel('相对频率') ax.set_title('各年月Yes相对频率及趋势') ax.legend() plt.xticks(rotation=45) plt.tight_layout() plt.show()
3. 高阶趋势拟合(可选)
如果数据呈现非线性趋势,只需修改多项式阶数即可,比如二次趋势:
# 拟合二次多项式 z = np.polyfit(x, y, 2) p = np.poly1d(z) ax.plot(x, p(x), color='green', linestyle='-.', label=f'二次趋势: y={z[0]:.6f}x² + {z[1]:.4f}x + {z[2]:.4f}')
内容的提问来源于stack exchange,提问作者Arthur Dent
相关产品推荐
相关产品推荐

