如何在DataFrame中正确计算MTD与YTD?需排除零值计算actuals累计平均
问题:修正MTD/YTD中actuals列的累计平均值计算(排除零值)
需求说明:
- 计算DataFrame的MTD(月初至今)和YTD(年初至今)指标
- bp列:MTD/YTD为累计平均值
- actuals列:MTD/YTD为排除零值后的累计平均值(actuals=0时不参与平均计算)
输入数据
import pandas as pd data = { 'date': ['2023-04-01', '2023-04-02', '2023-04-03', '2023-04-04', '2023-04-05'], 'category': ['QUALITY PARAMETERS', 'QUALITY PARAMETERS', 'QUALITY PARAMETERS', 'QUALITY PARAMETERS', 'QUALITY PARAMETERS'], 'parameter': ['TBR', 'TBR', 'TBR', 'TBR', 'TBR'], 'region': ['DELHI', 'DELHI', 'DELHI', 'DELHI', 'DELHI'], 'factory': ['ABC', 'ABC', 'ABC', 'ABC', 'ABC'], 'actuals': [10, 20, 0, 0, 10] } df = pd.DataFrame(data) df['date'] = pd.to_datetime(df['date'])
当前代码问题
原代码中mtd_bp和ytd_bp的逻辑正确,但mtd_actuals和ytd_actuals直接使用expanding().mean(),会把零值纳入计算,不符合"排除零值"的要求。
修正方案
核心思路
对于actuals列的累计平均,需要自定义计算逻辑:在每个累计窗口中,筛选出非零值后再求平均。可以用expanding().apply()实现该逻辑。
完整修正代码
# 1. 计算bp列的MTD/YTD(原逻辑保留,因为是普通累计平均) df['mtd_bp'] = df.groupby([df.date.dt.to_period('m'), 'category', 'parameter', 'region', 'factory'])\ .actuals.expanding().mean().droplevel([0, 1, 2, 3, 4]) df['ytd_bp'] = df.groupby([df.date.dt.to_period('A-MAR'), 'category', 'parameter', 'region', 'factory'])\ .actuals.expanding().mean().droplevel([0, 1, 2, 3, 4]) # 2. 定义排除零值的累计平均函数 def non_zero_expanding_mean(s): non_zero_vals = s[s != 0] return non_zero_vals.mean() if len(non_zero_vals) > 0 else 0 # 无有效值时返回0,可根据需求调整 # 3. 计算actuals列的MTD/YTD df['mtd_actuals'] = df.groupby([df.date.dt.to_period('m'), 'category', 'parameter', 'region', 'factory'])\ .actuals.expanding().apply(non_zero_expanding_mean, raw=False).droplevel([0, 1, 2, 3, 4]) df['ytd_actuals'] = df.groupby([df.date.dt.to_period('A-MAR'), 'category', 'parameter', 'region', 'factory'])\ .actuals.expanding().apply(non_zero_expanding_mean, raw=False).droplevel([0, 1, 2, 3, 4])
结果验证
修正后mtd_actuals的计算结果为:
| 日期 | actuals | mtd_actuals |
|---|---|---|
| 2023-04-01 | 10 | 10.0 |
| 2023-04-02 | 20 | 15.0 |
| 2023-04-03 | 0 | 15.0 |
| 2023-04-04 | 0 | 15.0 |
| 2023-04-05 | 10 | 13.333... |
完全符合"排除零值后累计平均"的要求。
内容的提问来源于stack exchange,提问作者AbinBenny
相关产品推荐
相关产品推荐

