如何对Pandas分组Series的累积和减去每组首个元素?
问题描述
我有一个pandas的series.groupby对象,命名为data,其输出示例如下:
<pandas.core.groupby.generic.SeriesGroupBy object at ***> (1, 0 397.44 1 12.72 2 422.40 Name: value, dtype: float64) (2, 3 398.88 4 6.48 5 413.52 Name: value, dtype: float64) (3, 6 398.40 7 68.40 8 18.96 9 56.64 10 406.56 Name: value, dtype: float64) (4, 11 398.64 12 14.64 13 413.76 Name: value, dtype: float64) ...
我希望得到一个等效对象,其中每个分组的条目为该组的累积和减去组内第一个元素,例如第一个分组应变为:
(1, 0 0 #(= 397.44 - 397.44) 1 12.72 #(= 397.44 + 12.72 - 397.44) 2 435.12 #(= 397.44 + 12.72 + 422.40 - 397.44)
我可以用apply轻松获取累积和:
cumulative_sums = data.apply(lambda x: x.cumsum())
但尝试用lambda x: x.cumsum()-x[0]减去组内第一个元素时出现KeyError,请问如何实现需求?
解决方案
出现KeyError是因为分组后的Series索引不一定从0开始(比如第二个分组的索引是3、4、5),直接用x[0]会尝试访问索引为0的元素,而该分组里没有这个索引,所以报错。
下面是几种可行的实现方法:
- 方法1:用
iloc[0]按位置取组内第一个元素iloc是按元素的位置索引,不管Series的实际索引是什么,iloc[0]都能精准拿到组内第一个元素:
result = data.apply(lambda x: x.cumsum() - x.iloc[0])
- 方法2:用
transform实现高效计算
这种方法比apply性能更优(数据量大时差异明显),不需要写lambda:
cumulative_sums = data.cumsum() group_first = data.transform('first') result = cumulative_sums - group_first
- 方法3:提取组首值的单个数值进行计算
和方法1逻辑类似,通过.item()把组首值提取为单个数值,避免潜在的索引对齐问题:
result = data.apply(lambda x: x.cumsum() - x.iloc[0].item())
内容的提问来源于stack exchange,提问作者KBriggs
相关产品推荐
相关产品推荐

