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

Python Pandas:基于累计和扣除DataFrame金额,如何生成amount_extra列?

问题:按顺序扣除金额并记录超额支付

数据准备

现有两个DataFrame:

import pandas as pd

df1 = pd.DataFrame({
    'name': ['virat', 'virat', 'virat', 'virat', 'virat', 'rohit', 'rohit'],
    'amount': [1000, 500, 200, 500, 150, 120, 100]})
df2 = pd.DataFrame({
    'name': ['virat', 'rohit'],
    'amount_paid': [1400, 300]})

需求说明

df2的name字段唯一,需使用df2的amount_paid列,按顺序扣除df1中对应name的amount值,直至amount_paid耗尽;若存在超额支付金额,新增amount_extra列记录该值(仅在对应name的最后一行显示超额金额,其余行显示0)。

预期输出

name    amount_left   amount_used_to_knock_off      amount_extra
0   virat   0                1000                          0
1   virat   100               400                          0
2   virat   200                 0                          0
3   virat   500                 0                          0
4   virat   150                 0                          0
5   rohit   0                 120                          0
6   rohit   0                 100                         80

已实现的代码及当前输出

以下代码已成功生成amount_left和amount_used_to_knock_off列,但缺少amount_extra列:

s = (df1
 .groupby('name')['amount'].cumsum()
 .sub(df1['name'].map(df2.set_index('name')['amount_paid']))
)

df1['amount_left'] = df1['amount'].mask(s.lt(df1['amount']), s.clip(lower=0))

df1['amount_used_to_knock_off'] = (df1['amount'].sub(s).clip(lower=0)
                                   .mask(s<0, df1['amount'])
                                   )

当前输出:

name  amount  amount_left  amount_used_to_knock_off
0  virat    1000            0                      1000
1  virat     500          100                       400
2  virat     200          200                         0
3  virat     500          500                         0
4  virat     150          150                         0
5  rohit     120            0                       120
6  rohit     100            0                       100

解决方案:新增amount_extra列

在现有代码基础上,添加以下逻辑计算超额支付金额:

简洁实现版

# 计算每个name的总金额
total_amount_per_name = df1.groupby('name')['amount'].transform('sum')
# 获取每个name对应的已支付金额
paid_per_name = df1['name'].map(df2.set_index('name')['amount_paid'])

# 初始化超额列
df1['amount_extra'] = 0
# 定位每个name的最后一行,计算并赋值超额金额
last_rows = df1.groupby('name').tail(1).index
df1.loc[last_rows, 'amount_extra'] = (paid_per_name - total_amount_per_name).loc[last_rows].clip(lower=0)

执行后即可得到符合预期的输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 12:21:08