如何用Pandas实现自定义年度周期的时间切片与月度求和聚合?
嘿,我刚好能帮你解决这个Pandas时间序列的问题!你提到的自定义年度周期和时段划分需求,完全可以用Pandas的内置工具搞定,不用写复杂的自定义函数,我给你一步步拆解:
核心思路
我们可以借助Pandas的时间频率标识和布尔筛选来实现:
- 用
AS-Nov这个内置频率字符串定义起始于11月的自定义年度; - 通过月份判断划分两个固定时段;
- 结合
resample(针对日度数据)和分组筛选完成聚合。
步骤1:处理示例/实际数据
先拿你提供的月度示例数据演示,实际日度数据只需要多一步转月度求和:
import pandas as pd import numpy as np # 你的示例月度数据 idx = pd.Series(pd.date_range("2016-11-1", freq="M", periods=48)) dft = pd.DataFrame(np.random.randn(48,1),columns=["NW"], index=idx) # 如果是实际日度数据,先转成月度求和(关键一步!) # daily_df = pd.read_csv("your_daily_data.csv", index_col=0, parse_dates=True) # dft = daily_df.resample('M').sum() # 按月份聚合求和
步骤2:标记自定义年度和时段
给每条数据添加两个标签:所属的自定义年度、所属的分析时段:
# 标记自定义年度:用"AS-Nov"表示年度起始于11月,转成字符串方便阅读 dft['custom_year'] = dft.index.to_period('AS-Nov').astype(str) # 标记分析时段:判断月份是否属于11-4月或5-10月 dft['period'] = np.where( dft.index.month.isin([11,12,1,2,3,4]), 'Nov-Apr', # 11月至次年4月 'May-Oct' # 5月至同年10月 )
步骤3:提取两个时段的月度求和序列
直接筛选出对应时段的数据,就是你需要用来画散点图的时间序列:
# 提取11月-次年4月的月度求和数据 nov_apr_series = dft[dft['period'] == 'Nov-Apr']['NW'] # 提取5月-10月的月度求和数据 may_oct_series = dft[dft['period'] == 'May-Oct']['NW']
步骤4:绘制散点图
用Matplotlib直接绘制两个时段的散点图(你也可以用Seaborn美化):
import matplotlib.pyplot as plt # 绘制Nov-Apr时段的散点图 plt.figure(figsize=(10,6)) plt.scatter(nov_apr_series.index, nov_apr_series.values) plt.title('Monthly Sum of NW (Nov-Apr) Over 60 Years') plt.xlabel('Date') plt.ylabel('Total NW') plt.xticks(rotation=45) plt.tight_layout() plt.show() # 绘制May-Oct时段的散点图 plt.figure(figsize=(10,6)) plt.scatter(may_oct_series.index, may_oct_series.values) plt.title('Monthly Sum of NW (May-Oct) Over 60 Years') plt.xlabel('Date') plt.ylabel('Total NW') plt.xticks(rotation=45) plt.tight_layout() plt.show()
额外需求:按自定义年度聚合时段总和
如果你需要统计每个自定义年度内,两个时段的总求和(而不是月度求和),可以用分组聚合:
# 按自定义年度+时段分组,计算每个组的总和 annual_period_total = dft.groupby(['custom_year', 'period'])['NW'].sum().unstack() print(annual_period_total)
关键知识点解释
AS-Nov是Pandas内置的频率代码:AS代表年度起始(Annual Start),Nov指定起始月份为11月,完美匹配你自定义年度的需求,不用自己写逻辑判断。resample('M').sum()是Pandas处理时间序列聚合的标准方法,日度转月度、季度转年度都可以用它,灵活高效。- 用
np.where结合dt.month.isin()做时段划分,比自定义函数更简洁,可读性也更强。
内容的提问来源于stack exchange,提问作者TommiWe
相关产品推荐
相关产品推荐

