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

Pandas groupby.diff问题:如何避免组间跨行计算差值

问题描述

我有一个已排序的Pandas DataFrame如下:

instrumentExtId Date                proxyMethod     isForceXS   xsValue     curveValue
.ID1            2008-03-28 00:00:00 CrossSectional  FALSE       6.86046681  6.86046681
.ID1            2008-03-31 00:00:00 CrossSectional  FALSE       6.97468855  6.97468855
.ID1            2008-04-01 00:00:00 CrossSectional  FALSE       6.83893432  6.83893432
.ID1            2008-04-02 00:00:00 CrossSectional  FALSE       6.70250452  6.70250452
.ID2            2008-03-28 00:00:00 CrossSectional  FALSE       3.10441877  3.10441877
.ID2            2008-03-31 00:00:00 CrossSectional  FALSE       3.5104612   3.5104612
.ID2            2008-04-01 00:00:00 CrossSectional  FALSE       3.52994089  3.52994089
.ID2            2008-04-02 00:00:00 CrossSectional  FALSE       3.24236585  3.24236585

需求为:对每个instrumentExtId,先对xsValue和curveValue列应用反双曲正弦函数(np.arcsinh),再计算同ID内的日期间差值,同时保留proxyMethod和isForceXS列。

我编写了如下代码:

df = df.groupby(['instrumentExtId', 'Date', 'proxyMethod', 'isForceXS'], group_keys = True)[["xsValue","curveValue"]].\
        apply(lambda x:np.arcsinh(x)). \
        diff(). \
        reset_index().\
        drop(["level_4"], axis=1)

但运行结果中第二个ID的第一行,差值是该ID首行与前一个ID末行的计算结果,我期望此处为nan,请问问题出在哪里?

运行结果如下:

instrumentExtId Date                proxyMethod    isForceXS    xsValue      curveValue
.ID1            2008-03-28 00:00:00 CrossSectional  FALSE       nan          nan
.ID1            2008-03-31 00:00:00 CrossSectional  FALSE       0.016342295   0.016342295
.ID1            2008-04-01 00:00:00 CrossSectional  FALSE       -0.01945289  -0.01945289
.ID1            2008-04-02 00:00:00 CrossSectional  FALSE       -0.019934368 -0.019934368
.ID2            2008-03-28 00:00:00 CrossSectional  FALSE       -0.750188187 -0.75018818
.ID2            2008-03-31 00:00:00 CrossSectional  FALSE        0.117631041  0.117631041
.ID2            2008-04-01 00:00:00 CrossSectional  FALSE        0.005323083  0.005323083
.ID2            2008-04-02 00:00:00 CrossSectional  FALSE       -0.081488875 -0.081488875
问题原因与解决方法

问题根源

你的代码逻辑存在两个核心问题:

  1. 分组维度错误:你用['instrumentExtId', 'Date', 'proxyMethod', 'isForceXS']分组,这会把每个**(ID+日期+proxyMethod+isForceXS)**组合拆成独立小组,apply(np.arcsinh)只是对单个小组的数值做转换,无法实现按ID批量处理。
  2. 全局计算差值:后续的diff()是对整个DataFrame做全局差值计算,而非在每个instrumentExtId组内计算,导致.ID2的第一行会和.ID1的最后一行做差,而非保留nan。

正确实现代码

分步写法(更直观)

# 第一步:对目标列应用反双曲正弦函数
df[['xsValue', 'curveValue']] = np.arcsinh(df[['xsValue', 'curveValue']])

# 第二步:按instrumentExtId分组,在组内计算差值
df[['xsValue', 'curveValue']] = df.groupby('instrumentExtId')[['xsValue', 'curveValue']].diff()

链式写法(更简洁)

df = df.assign(
    xsValue=np.arcsinh(df['xsValue']),
    curveValue=np.arcsinh(df['curveValue'])
).groupby('instrumentExtId')[['xsValue', 'curveValue']].diff().assign(
    instrumentExtId=df['instrumentExtId'],
    Date=df['Date'],
    proxyMethod=df['proxyMethod'],
    isForceXS=df['isForceXS']
)[['instrumentExtId', 'Date', 'proxyMethod', 'isForceXS', 'xsValue', 'curveValue']]

以上两种写法都会让每个ID的首行差值为nan,后续行仅在同ID内计算日期间差值,完全符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 23:40:22