如何在DataFrame中按组生成符合指定规则的average列
问题描述
现有如下DataFrame:
| id | value |
|---|---|
| a | 2 |
| a | 4 |
| a | 3 |
| a | 5 |
| b | 1 |
| b | 4 |
| b | 3 |
| c | 1 |
| c | nan |
| c | 5 |
需要生成包含新列average的结果DataFrame,取值规则如下:
- 按
id执行group-by分组 - 每组中
average列的首行值等于对应行的value值 - 组内其他行的
average值为该之前所有value行(不含当前值)的均值
最终目标结果DataFrame如下:
| id | value | average |
|---|---|---|
| a | 2 | 2 |
| a | 4 | 2 |
| a | 3 | 3 |
| a | 5 | 3 |
| b | 1 | 1 |
| b | 4 | 1 |
| b | 3 | 2.5 |
| c | 1 | 1 |
| c | nan | 1 |
| c | 5 | 1 |
解决方案
可以通过Pandas分组结合累积统计与移位操作实现需求,代码如下:
import pandas as pd import numpy as np # 构造原始DataFrame df = pd.DataFrame({ 'id': ['a', 'a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c'], 'value': [2, 4, 3, 5, 1, 4, 3, 1, np.nan, 5] }) def calculate_avg(group): # 计算组内value的累积和(自动忽略NaN) cum_sum = group['value'].cumsum() # 统计组内到当前行的非NaN值数量 cum_count = group['value'].notna().cumsum() # 首行直接取value,其他行用前序所有行的均值 group['average'] = np.where( cum_count == 1, group['value'], (cum_sum.shift(1) / cum_count.shift(1)).fillna(group['value']) ) return group # 分组应用计算逻辑 result_df = df.groupby('id', group_keys=False).apply(calculate_avg) print(result_df)
代码说明
cumsum():计算每组value的累积和,自动跳过NaN值notna().cumsum():统计每组截至当前行的有效数值(非NaN)数量shift(1):将累积统计结果向下偏移一行,让当前行能获取到之前所有行的总和与数量np.where:区分首行与其他行的计算逻辑,首行直接取原value,其他行用前序数值的均值填充
运行代码后得到的结果与目标DataFrame完全一致。
内容的提问来源于stack exchange,提问作者ii mm
相关产品推荐
相关产品推荐

