如何在Pandas GroupBy中用一行代码结合pct_change与cumprod计算
Pandas GroupBy分组下基于组首元素计算累计涨跌幅的简洁实现
在Pandas的GroupBy分组处理场景中,需要基于每组的首个元素计算累计涨跌幅(类似全局pct_change后cumprod的效果,但按组独立计算)。现有代码可运行但分成了两步GroupBy操作,想简化成一行代码实现。
原代码
import pandas as pd import numpy as np data = [[1, 10], [2, 17], [3, 15],[4, 11], [5, 17], [6, 15]] df = pd.DataFrame(data, columns=["id", "open"]) # 全局累计涨跌幅 df['Normal'] = df['open'].pct_change().fillna(0).add(1).cumprod().sub(1).mul(100).round(2) # 分组计算(分两步) df["Group_of_3"] = df.groupby(np.arange(len(df)) // 3 )["open"].pct_change().fillna(0).add(1) df["Group_of_3"] = df.groupby(np.arange(len(df)) // 3 )["Group_of_3"].cumprod().sub(1).mul(100).round(2) print(df)
原输出结果
id open Normal Group_of_3 0 1 10 0.0 0.00 1 2 17 70.0 70.00 2 3 15 50.0 50.00 3 4 11 10.0 0.00 4 5 17 70.0 54.55 5 6 15 50.0 36.36
优化方案
方案1:直接基于组内首元素计算(性能更优)
跳过pct_change和cumprod的组合,直接用每组的open值与组内首个元素做比值计算,一步完成所有转换:
df["Group_of_3"] = df.groupby(np.arange(len(df)) // 3)["open"].transform( lambda x: (x / x.iloc[0] - 1).mul(100).round(2) )
方案2:链式调用原逻辑(保留原有计算步骤)
如果要严格遵循原代码的pct_change→cumprod逻辑,可通过groupby.apply将每组的处理逻辑封装为lambda函数,一次性完成操作:
df["Group_of_3"] = df.groupby(np.arange(len(df)) // 3)["open"].apply( lambda x: x.pct_change().fillna(0).add(1).cumprod().sub(1).mul(100).round(2) ).reset_index(drop=True)
说明
- 方案1的计算逻辑更直接,避免了多次累计乘积运算,性能更高效,且输出结果与原代码完全一致。
- 方案2完整保留原有的计算链路,适合需要严格对齐原逻辑的场景。
内容的提问来源于stack exchange,提问作者prem
相关产品推荐
相关产品推荐

