基于工作日DateTimeIndex的Pandas切片求均值优化方案咨询
我来帮你搞定这两个需求的高效实现,彻底摆脱循环的低效问题~
方案1:每月第m到n个工作日的均值(向量化实现)
核心思路是先给每个日期标记它在当月的工作日排名,再通过布尔筛选+分组聚合完成计算,全程无需循环:
import pandas as pd # 先构造你的示例数据 df = pd.DataFrame(list(range(91)), pd.date_range('2015-04-01', '2015-6-30'), columns=['foo']).resample('B').last() marker_dates = [df.index[12], df.index[33], df.index[57]] # 步骤1:计算每个日期在当月的工作日排名(从1开始计数) df['monthly_bday_rank'] = df.index.to_series().groupby(df.index.to_period('M')).rank(method='first', ascending=True).astype(int) # 步骤2:设定要统计的工作日范围(比如第2到第4个工作日) m, n = 2, 4 # 步骤3:筛选符合范围的行,按月份分组计算foo的均值 monthly_range_mean = df[df['monthly_bday_rank'].between(m, n)].groupby(df.index.to_period('M'))['foo'].mean() # 查看结果 print(monthly_range_mean)
解释:
groupby(df.index.to_period('M'))按月份分组,rank(method='first')保证每个工作日按顺序得到唯一的排名(避免日期重复的情况)- 布尔筛选
df['monthly_bday_rank'].between(m, n)直接定位到目标行,后续的groupby.mean()是Pandas原生的高效聚合操作,性能远优于循环。
方案2:标记日前后m到n天的均值(优化方案)
这里的关键是准确计算每个日期相对于对应月份标记日的工作日偏移量,再筛选偏移量在目标范围内的行进行聚合:
# 步骤1:创建「月份-标记日」的映射字典,方便快速匹配每个日期对应的标记日 month_marker_map = {dt.to_period('M'): dt for dt in marker_dates} # 步骤2:添加月份列,并匹配对应标记日 df['month'] = df.index.to_period('M') df['marker_date'] = df['month'].map(month_marker_map) # 步骤3:计算每个日期相对于标记日的工作日偏移量(用BDay()来计算工作日间隔) from pandas.tseries.offsets import BDay df['offset'] = df.index.to_series().apply(lambda x: (x - month_marker_map[x.to_period('M')]) / BDay()) # 步骤4:设定窗口范围(比如标记日前后1天,即偏移量-1到+1) m, n = 1, 1 # 步骤5:筛选窗口内的行,按月份分组计算均值 marker_window_mean = df[df['offset'].between(-m, n)].groupby('month')['foo'].mean() # 查看结果(和你示例中的4月16、17、20日均值一致) print(marker_window_mean)
解释:
(x - marker_date) / BDay()会自动计算两个日期之间的工作日间隔数,比如标记日是周五,下一个工作日周一的偏移量是+1,完美符合你的需求- 整个流程通过映射和向量化操作完成,避免了循环遍历标记日的低效操作,大数据集下性能提升明显。
内容的提问来源于stack exchange,提问作者user3556757
相关产品推荐
相关产品推荐

