使用Pandas计算月度支出移动平均及resample报错问题咨询
解决月度平均支出及6个月移动平均的绘制问题
首先,你遇到的resample错误核心原因很明确:resample方法要求DataFrame/Series的索引是DatetimeIndex、TimedeltaIndex或PeriodIndex类型,而你的当前索引是默认的RangeIndex(数字索引)——哪怕Date_of_event是datetime列也没用,resample是基于索引工作的,不是普通列。
下面给你两种可行的解决方案,从数据处理到绘图一步到位:
方案一:使用resample(推荐,更简洁)
步骤1:标准化日期列并设置为索引
先确保你的日期列是datetime类型(你说已经能使用dt方法,这一步可能已经完成,但还是可以加一行确认),然后将其设置为DataFrame的索引:
import pandas as pd # 确保日期列是datetime类型(如果还没转换的话) df['Date_of_event'] = pd.to_datetime(df['Date_of_event']) # 将日期列设置为DataFrame的索引 df = df.set_index('Date_of_event')
步骤2:计算月度平均支出
现在索引是DatetimeIndex,就可以正常使用resample了:
# 按日历月重采样,计算月度平均支出 monthly_avg_exp = df['expenditure'].resample('M').mean()
这里'M'表示按自然月聚合,mean()会自动计算每个月的支出平均值。
步骤3:计算6个月移动平均
用rolling方法实现滚动平均:
# 计算连续6个月份的滚动平均(window=6表示取最近6个月的数据计算均值) six_month_rolling_avg = monthly_avg_exp.rolling(window=6).mean()
方案二:使用groupby按年月分组
如果不想修改DataFrame的索引,也可以提取年月作为分组键来计算月度平均:
# 提取年月信息,转为Period类型(保证时间顺序的一致性) df['year_month'] = df['Date_of_event'].dt.to_period('M') # 按年月分组计算平均支出 monthly_avg_exp = df.groupby('year_month')['expenditure'].mean() # 必须排序,否则移动平均会因为时间乱序出错 monthly_avg_exp = monthly_avg_exp.sort_index() # 同样计算6个月移动平均 six_month_rolling_avg = monthly_avg_exp.rolling(window=6).mean()
用Seaborn/Matplotlib绘图
用Matplotlib绘制:
import matplotlib.pyplot as plt plt.figure(figsize=(10, 6)) # 绘制月度平均支出 monthly_avg_exp.plot(marker='o', label='月度平均支出') # 绘制6个月移动平均 six_month_rolling_avg.plot(marker='s', label='6个月移动平均') plt.title('月度平均支出与6个月移动平均') plt.xlabel('年月') plt.ylabel('支出金额') plt.legend() plt.xticks(rotation=45) plt.tight_layout() # 自动调整布局,避免标签被截断 plt.show()
用Seaborn绘制(更美观):
需要先将Series转为DataFrame,适配Seaborn的输入格式:
import seaborn as sns import matplotlib.pyplot as plt # 将数据整理为长格式DataFrame plot_data = pd.DataFrame({ '年月': monthly_avg_exp.index.astype(str), # 将Period转为字符串,方便x轴显示 '月度平均支出': monthly_avg_exp.values, '6个月移动平均': six_month_rolling_avg.values }).melt(id_vars='年月', var_name='指标', value_name='支出金额') plt.figure(figsize=(10, 6)) sns.lineplot(data=plot_data, x='年月', y='支出金额', hue='指标', marker='o') plt.title('月度平均支出与6个月移动平均') plt.xlabel('年月') plt.ylabel('支出金额') plt.xticks(rotation=45) plt.tight_layout() plt.show()
额外说明:
你之前的错误代码df['Date_of_event'] = df['Date_time'].resample('M')有两个问题:
- 列名可能写错了(你的数据里是
Date_of_event,不是Date_time); resample不能直接赋值给普通列,它需要作用在带时间索引的Series/DataFrame上,返回的是重采样后的结果,不是修改原列。
内容的提问来源于stack exchange,提问作者Calvin77
相关产品推荐
相关产品推荐

