如何在Pandas中实现带重置规则的累计求和并生成条件列?
问题描述
示例DataFrame
| group 1 | group 2 | cond 1 | point | total_capacity |
|---|---|---|---|---|
| A | 1 | 0 | 0.3 | 2 |
| A | 1 | 1 | 0.5 | 2 |
| A | 1 | 0 | 0.8 | 2 |
| A | 1 | 0 | 0.2 | 2 |
| A | 1 | 0 | 0.4 | 2 |
| B | 2 | 0 | 0.6 | 4 |
| B | 2 | 0 | 0.3 | 4 |
| B | 2 | 1 | 0.1 | 4 |
| B | 2 | 0 | 0.4 | 4 |
| B | 3 | 0 | 0.5 | 4 |
| B | 3 | 0 | 0.2 | 4 |
需求
生成值为0/1的新列,规则如下:
- 按
group 1+group 2分组,仅对cond 1=1的行进行判断 - 计算当前行及之后所有行的
point累计和,累计和达到1.1时重置为0,统计重置次数 - 若重置次数 ≤
total_capacity,对应行新列值为1,否则为0
尝试的代码
df['new_col'] = 0 for index, row in df.iterrows(): if row['cond_1'] == 1: group_1 = row['group_1'] group_2 = row['group_2'] total_capacity = row['total_capacity'] point = row['point'] remaining_point = df[(df['group_1'] == group_1) & (df['group_2'] == group_1) & (df.index >= index)]['point'].sum() remaining_cap = remaining_point / 1.1 if (remaining_cap < total_capacity): combined_df.at[index, 'new_col'] = 1
遇到的问题
无法将"累计求和重置"的规则整合到代码中。例如第一组(A-1)按原逻辑会将new_col设为1,但按重置规则统计的次数为3>2,因此new_col应设为0。
预期输出
| group 1 | group 2 | cond 1 | point | total_capacity | new_c |
|---|---|---|---|---|---|
| A | 1 | 0 | 0.3 | 2 | 0 |
| A | 1 | 1 | 0.5 | 2 | 0 |
| A | 1 | 0 | 0.8 | 2 | 0 |
| A | 1 | 0 | 0.2 | 2 | 0 |
| A | 1 | 0 | 0.4 | 2 | 0 |
| B | 2 | 0 | 0.6 | 4 | 0 |
| B | 2 | 0 | 0.3 | 4 | 0 |
| B | 2 | 1 | 0.1 | 4 | 1 |
| B | 2 | 0 | 0.4 | 4 | 0 |
| B | 3 | 0 | 0.5 | 4 | 0 |
| B | 3 | 0 | 0.2 | 4 | 0 |
解决方案
核心思路
针对每个group 1+group 2分组,找到cond 1=1的行,模拟point累计求和并重置的过程,统计重置次数后与total_capacity比较,设置新列值。
实现代码
import pandas as pd # 构造示例DataFrame df = pd.DataFrame({ 'group 1': ['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B'], 'group 2': [1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3], 'cond 1': [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0], 'point': [0.3, 0.5, 0.8, 0.2, 0.4, 0.6, 0.3, 0.1, 0.4, 0.5, 0.2], 'total_capacity': [2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4] }) df['new_c'] = 0 # 遍历每个分组 for (g1, g2), group in df.groupby(['group 1', 'group 2']): # 找到分组中cond1=1的行索引 cond1_rows = group[group['cond 1'] == 1].index for idx in cond1_rows: # 获取当前行及之后的point序列 points = group.loc[idx:, 'point'].tolist() current_sum = 0.0 reset_count = 0 # 模拟累计求和重置过程 for p in points: current_sum += p # 累计和达到或超过1.1时重置,次数+1 while current_sum >= 1.1: reset_count += 1 current_sum -= 1.1 # 若最后仍有剩余未填满的和,额外算一次重置(匹配用户预期的A组次数) if current_sum > 0: reset_count += 1 # 比较次数与容量,设置新列值 total_capacity = group.loc[idx, 'total_capacity'] df.loc[idx, 'new_c'] = 1 if reset_count <= total_capacity else 0 print(df)
代码说明
- 分组遍历:按
group 1和group 2拆分数据,确保只处理同组内的行 - 累计重置模拟:逐个累加
point,每次累计和≥1.1时重置并计数,剩余未填满的部分额外算一次重置(匹配用户预期的A组次数逻辑) - 值设置:根据重置次数与
total_capacity的比较结果,设置new_c的值
内容的提问来源于stack exchange,提问作者deeni
相关产品推荐
相关产品推荐

