You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas DataFrame条件处理:使用sum()累加并按规则删除行

Pandas 按id分组累加quantity并过滤行

处理规则

对给定的pandas DataFrame按如下逻辑处理:

  • 按id字段分组遍历数据
  • 若同一id对应多行且组内quantity存在负值,逐行累加quantity做核销处理
  • 累加/核销后结果为0或负数的行直接删除,结果为正数的行保留

示例数据

输入df:

import pandas as pd
df = pd.DataFrame({
    'id': ['1a','1a','b5','b5','1a','1a'],
    'date':['11-01-22', '12-01-22', '13-01-22', '21-01-22', '11-01-22', '18-01-22'],
    'quantity':[2,5,3,-1,-2,2]
})

预期输出结果:

result = pd.DataFrame({
    'id': ['1a','b5','1a'],
    'date':['12-01-22', '13-01-22','18-01-22'],
    'quantity':[5,2,2]
})

实现方案

核心逻辑是先合并同id同日期的记录,再按时间顺序用负值逐笔核销之前的正值记录,核销完的负值记录直接丢弃,被核销为0的正值记录也丢弃,剩余的正值记录按日期排序即为结果:

# 按id、date分组聚合,合并同一天同id的正负数量
df_agg = df.groupby(['id', 'date'], as_index=False)['quantity'].sum()
# 过滤聚合后数量为0的记录,按时序排序
df_agg = df_agg[df_agg['quantity'] != 0].sort_values(['id', 'date']).reset_index(drop=True)

result_rows = []
# 按id分组处理负值核销
for _, group in df_agg.groupby('id', sort=False):
    group = group.sort_values('date').reset_index(drop=True)
    pos_buffer = []
    for _, row in group.iterrows():
        current_qty = row['quantity']
        if current_qty > 0:
            pos_buffer.append(row.copy())
        else:
            remain_neg = abs(current_qty)
            # 从最近的正值记录开始核销
            while remain_neg > 0 and pos_buffer:
                last_pos = pos_buffer[-1]
                if last_pos['quantity'] > remain_neg:
                    last_pos['quantity'] -= remain_neg
                    remain_neg = 0
                else:
                    remain_neg -= last_pos['quantity']
                    pos_buffer.pop()
    result_rows.extend(pos_buffer)

# 转换为DataFrame,按日期排序重置索引
result = pd.DataFrame(result_rows).sort_values('date').reset_index(drop=True)

执行代码后得到的结果与预期完全一致。

内容的提问来源于stack exchange,提问作者user18977534

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 02:48:32