Pandas如何计算每月内唯一日期对应n个最大值的平均值
实现方案
前置处理说明
如果你的数据集只有时间戳列,必须先拆分出月、日维度列,后续按月分组、按日去重的操作都依赖这两个维度,拆分直接用pandas时间序列接口即可:
# 先确保时间戳列是datetime格式 df['timestamp'] = pd.to_datetime(df['timestamp']) df['month'] = df['timestamp'].dt.month df['day'] = df['timestamp'].dt.day
如果已经有month和day列可以跳过这一步。
原有代码问题
你之前写的代码:df.groupby(['month', 'day'])['value'].transform(lambda x: x.nlargest(3).mean())
分组粒度是「月+日」,计算的是单日范围内的前3大值均值,和你需要的「单月范围、每个日期仅取1个值参与topN计算」的逻辑顺序完全颠倒。
正确实现逻辑
需求的核心计算顺序是:
- 先按「月+日」分组,取每个日期的最大值,保证参与后续计算的记录日期唯一
- 再按「月」分组,取当月所有日最大值中的前n个,计算平均值
- 最后把月度计算结果回填到当月所有原始记录上
以你样例中n=2的场景为例,完整代码如下:
# 可根据需求修改n的取值,即每月取前多少个日最高值算平均 n = 2 # 步骤1:计算每个月每一天的最高值 daily_peak = df.groupby(['month', 'day'], as_index=False)['value'].max() # 步骤2:计算每个月前n个日最高值的平均值 monthly_avg = daily_peak.groupby('month')['value'].apply( lambda x: x.nlargest(n).mean() ).reset_index(name='peak_avg') # 步骤3:把月度结果关联回原始数据表 df = df.merge(monthly_avg, on='month', how='left')
样例校验
用你提供的测试数据运行上述代码,输出结果完全匹配预期:
| month | day | value | peak_avg (expected) | 代码输出peak_avg |
|---|---|---|---|---|
| 1 | 1 | 35 | 35 | 35 |
| 1 | 1 | 30 | 35 | 35 |
| 2 | 1 | 34 | 28.5 | 28.5 |
| 2 | 2 | 23 | 28.5 | 28.5 |
| 3 | 1 | 98 | 97 | 97 |
| 3 | 2 | 96 | 97 | 97 |
计算逻辑验证:
- 1月仅1个有效日最高值35,均值为35
- 2月2个日最高值为34、23,均值为(34+23)/2=28.5
- 3月2个日最高值为98、96,均值为(98+96)/2=97
内容的提问来源于stack exchange,提问作者NorwegianClassic
相关产品推荐
相关产品推荐

