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

如何在Pandas DataFrame中按ID计算特定rate差值并新增列?

Pandas按客户计算费率差值的解决方案

问题背景

原始DataFrame结构如下:

IDrateSequential number
a1501
a1501
a502
b2501
c251
d251
d402
d253

字段说明:

  • ID:客户唯一标识
  • rate:月度费率
  • Sequential number:客户每次更改费率时递增的序号

需求明确:
对每个ID,找到Sequential number最大值对应的rate,减去该ID下Sequential number最小值对应的rate,将差值作为新列rate_diff添加到DataFrame;若ID仅有一条记录,rate_diff为0。仅在该ID的最大序号行显示差值,其余行填0。

期望结果:

IDrateSequential numberrate_diff
a15010
a15010
a502-100
b25010
c2510
d2510
d4020
d3035

你之前尝试的代码:

df['diff_rate'] = df.groupby('ID')['rate'].transform(lambda x : x-x.min()) 

不符合预期的原因是:这段代码是用每条记录的rate减去该ID下rate的最小值,而非按Sequential number的最大、最小值对应的rate计算差值,也没实现仅在最大序号行显示差值的逻辑。

解决方案

可以通过分组提取每个ID的初始费率(最小序号对应rate)和最新费率(最大序号对应rate),再结合行序号判断计算差值:

方法一:分步实现

import pandas as pd

# 原始数据
data = [
    ['a', 150, 1],
    ['a', 150, 1],
    ['a', 50, 2],
    ['b', 250, 1],
    ['c', 25, 1],
    ['d', 25, 1],
    ['d', 40, 2],
    ['d', 30, 3]
]
df = pd.DataFrame(data, columns=['ID', 'rate', 'Sequential number'])

# 1. 提取每个ID的初始费率和最新费率
id_rate_info = df.groupby('ID').apply(
    lambda group: pd.Series({
        'initial_rate': group[group['Sequential number'] == group['Sequential number'].min()]['rate'].iloc[0],
        'latest_rate': group[group['Sequential number'] == group['Sequential number'].max()]['rate'].iloc[0]
    })
).reset_index()

# 2. 合并回原DataFrame
df = df.merge(id_rate_info, on='ID', how='left')

# 3. 计算rate_diff:仅最大序号行显示差值,其余为0
df['rate_diff'] = df.apply(
    lambda row: row['latest_rate'] - row['initial_rate'] 
    if row['Sequential number'] == df[df['ID'] == row['ID']]['Sequential number'].max() 
    else 0,
    axis=1
)

# 4. 清理中间列(可选)
df.drop(['initial_rate', 'latest_rate'], axis=1, inplace=True)

print(df)

方法二:更简洁的transform写法

import pandas as pd

# 原始数据同上
df = pd.DataFrame(data, columns=['ID', 'rate', 'Sequential number'])

# 获取每个ID的最大序号
df['max_seq'] = df.groupby('ID')['Sequential number'].transform('max')

# 获取每个ID的初始费率(最小序号对应的rate)
df['initial_rate'] = df.groupby('ID').apply(
    lambda g: g[g['Sequential number'] == g['Sequential number'].min()]['rate'].iloc[0]
).reset_index(level=0, drop=True)

# 获取每个ID的最新费率(最大序号对应的rate)
df['latest_rate'] = df.groupby('ID').apply(
    lambda g: g[g['Sequential number'] == g['Sequential number'].max()]['rate'].iloc[0]
).reset_index(level=0, drop=True)

# 计算差值
df['rate_diff'] = df.apply(
    lambda x: x['latest_rate'] - x['initial_rate'] if x['Sequential number'] == x['max_seq'] else 0,
    axis=1
)

# 清理中间列
df.drop(['max_seq', 'initial_rate', 'latest_rate'], axis=1, inplace=True)

print(df)

两种方法都能得到符合预期的结果,核心是先定位每个ID的最小/最大序号对应的费率,再判断当前行是否是最大序号行,进而计算差值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 10:25:35