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

如何在DataFrame分组中跨不同索引实现PL与Position的除法运算

问题:跨日期分组计算比值列

现有DataFrame结构

构造的DataFrame以Position Date、Client、Product、Buy Date为多层索引,包含Position和PL两列,初始数据如下:

Position DateClientProductBuy DatePositionPL
2022-01-02Client 1Product 12022-05-021300
2022-01-02Client 1Product 42022-06-0250000
2022-01-02Client 2Product 22022-03-121200
2022-01-02Client 2Product 32022-01-25770
2022-01-03Client 1Product 42022-06-0270002000
2022-01-03Client 2Product 22022-03-1220080
2022-01-03Client 2Product 32022-01-2510023

构造代码:

import pandas as pd

df = pd.DataFrame()
df['Client'] = ['Client 1', 'Client 1','Client 2','Client 2', 'Client 1', 'Client 2','Client 2']
df['Product'] = ['Product 1', 'Product 4', 'Product 2', 'Product 3',  'Product 4', 'Product 2', 'Product 3']
df['Position Date'] = ['2022-01-02', '2022-01-02', '2022-01-02', '2022-01-02', '2022-01-03', '2022-01-03', '2022-01-03']
df['Buy Date'] = ['2022-05-02', '2022-06-02', '2022-03-12', '2022-01-25', '2022-06-02', '2022-03-12', '2022-01-25']
df['Position'] = [130, 5000, 120, 77,  7000, 200, 100]
df['PL'] = [0,0,0,0, 50, 2000, 80, 100]

df = df.set_index(['Position Date','Client',  'Product', 'Buy Date'], drop=True)

df['PL'] = df.groupby(level=['Client', 'Product', 'Buy Date']).diff().fillna(0)

需求:创建新列X

新列X的计算规则:

  • 首日(最早的Position Date)的X值为0
  • 非首日的X值 = 当日的PL值 ÷ 该Client-Product-Buy Date分组上一日的Position值

举个例子:2022-01-03当天,Client 2、Product 2的X值 = 80 ÷ 120(120是2022-01-02该分组的Position值)

预期最终结果中,非首日的X值分别为:2000/5000、80/120、23/77

之前方案的问题

之前使用基于reindex的方案:

df['output'] = df['PL'].div(df.loc[df.index[0][0], 'Position']
                          .reindex(df.droplevel('Position Date').index).values
                       )

但当不同Position Date的分组结构不一致时(比如2022-01-03的Client 1分组比2022-01-02少了Product 1的条目),该方案无法正确匹配分组,导致计算错误。

解决方案

通过按Client-Product-Buy Date分组后,对每个分组内的Position进行移位实现,不受分组结构变化的影响:

# 按Client、Product、Buy Date分组,提取上一日的Position值
prev_position = df.groupby(level=['Client', 'Product', 'Buy Date'])['Position'].shift(1)

# 计算X列:PL除以移位后的Position,首日无数据填充为0
df['X'] = df['PL'].div(prev_position).fillna(0)

逻辑说明

  • groupby(level=['Client', 'Product', 'Buy Date'])确保仅在同一客户-产品-购买日期的分组内处理数据
  • shift(1)将每个分组内的Position值向上移动一行,正好对应上一日的Position数据
  • 首日的移位结果为NaN,用fillna(0)填充为0,符合需求

验证结果

执行后df['X']的结果如下:

Position DateClientProductBuy DateX
2022-01-02Client 1Product 12022-05-020.0
2022-01-02Client 1Product 42022-06-020.0
2022-01-02Client 2Product 22022-03-120.0
2022-01-02Client 2Product 32022-01-250.0
2022-01-03Client 1Product 42022-06-020.4
2022-01-03Client 2Product 22022-03-120.666...
2022-01-03Client 2Product 32022-01-250.2987...

完全符合预期,且不受不同日期分组结构差异的影响。


内容的提问来源于stack exchange,提问作者João Weckerle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 14:21:00