发布于2026-07-17 阅读(0)
扫一扫,手机访问
在数据分析的日常工作中,经常遇到这样一个场景:需要根据特定的分组条件——比如相同的时间点加上相同的类别标签——去计算某个数值字段相对于前一条记录的变化量,也就是一阶差分。很多人第一反应是写好几层 for 循环,挨个遍历不同的组合,再手动算差值。这种方法在小规模数据上还能应付,可一旦数据量上来,性能问题立刻就暴露了,代码也容易写得又长又乱,调试起来相当头疼。
其实,Pandas 提供了一套非常简洁高效的向量化方案,核心就是一句话:groupby(...)[col].diff()。它的逻辑很清晰:先按你指定的列(比如 ['Time', 'Prop1'])进行分组,然后在每个组内,对目标列(比如 Prop2)按照原始行顺序计算当前行与上一行的差值,也就是 current - previous。对于每个组的第一条记录,因为前面没有数据,所以直接返回 NaN。
直接看一个完整的例子,会更直观:
import pandas as pd
# 构造示例数据
df = pd.DataFrame({
"Time": [1, 2, 3, 1, 2, 3],
"Prop1": ["A", "B", "A", "A", "B", "B"],
"Prop2": [4, 5, 1, 5, 4, 3]
})
# 关键操作:按 Time 和 Prop1 分组,对 Prop2 计算组内差分
df["Prop2Diff"] = df.groupby(['Time', 'Prop1'])['Prop2'].diff()
print(df)
运行结果如下:
Time Prop1 Prop2 Prop2Diff 0 1 A 4 NaN 1 2 B 5 NaN 2 3 A 1 NaN 3 1 A 5 1.0 4 2 B 4 -1.0 5 3 B 3 NaN
这里面的逻辑其实一目了然:
Time=1, Prop1='A' 第一次出现,所以 Prop2Diff 是 NaN。Prop2 从 4 变成了 5,差值就是 5 - 4 = 1.0。Time=2, Prop1='B' 的首行,同样是 NaN。Prop2 从 5 降到 4,差值就是 4 - 5 = -1.0。Time=3 这个时间点上,每个分组都只有一条记录,没有前一行可比较,所以结果都是 NaN。不过,使用这个技巧时,有几个细节值得留意:
diff() 默认是按原始 DataFrame 的行顺序来计算组内差分的,并不会自动排序。如果你的业务逻辑要求必须按时间升序来算(比如分析时间序列数据),最好先对数据排序:df = df.sort_values(['Time', 'Prop1']).reset_index(drop=True) df['Prop2Diff'] = df.groupby(['Time', 'Prop1'])['Prop2'].diff()
groupby('Prop1').apply(lambda g: g.sort_values('Time')['Prop2'].diff())。diff(periods=n) 这个参数可以让你指定跨几行差分,比如 diff(2) 就是计算隔一行的差值。说到底,groupby([...])[col].diff() 就是处理“条件差分”这类问题的标准范式。逻辑清晰、代码简短、性能卓越,算是 Pandas 高效数据处理中一个非常实用的核心技巧。