我有一个数据框,其中一列表示时间,另一列表示键的其他部分。

df = pd.DataFrame(data=[(t, l1, l2, t * t * (1 + l2 + l1))
                        for t in range(3)
                        for l1 in [3, 4]
                        for l2 in [10, 100]],
                  columns=['t', 'l1', 'l2', 'x'])

    t   l1  l2  x
0   0   3   10  0
1   0   3   100 0
2   0   4   10  0
3   0   4   100 0
4   1   3   10  14
5   1   3   100 104
6   1   4   10  15
7   1   4   100 105
8   2   3   10  56
9   2   3   100 416
10  2   4   10  60
11  2   4   100 420

我正在查找前一个值为“t”的行的“x”列中的差异,但“l1”和“l2”的值相同。
    t   l1  l2  x   t.1 delta_x
0   0   3   10  0   1   NaN
1   0   3   100 0   1   NaN
2   0   4   10  0   1   NaN
3   0   4   100 0   1   NaN
4   1   3   10  14  2   14.0
5   1   3   100 104 2   104.0
6   1   4   10  15  2   15.0
7   1   4   100 105 2   105.0
8   2   3   10  56  3   42.0
9   2   3   100 416 3   312.0
10  2   4   10  60  3   45.0
11  2   4   100 420 3   315.0

我可以用下面的代码生成这个框架。
df['t.1'] = df.t + 1
df['delta_x'] = df.x - df.merge(df, left_on=['t', 'l1', 'l2'],
                                right_on=['t.1', 'l1', 'l2'],
                                how='left',
                                suffixes=['','.1'])['x.1']

有没有更干净或更有效的方法来做到这一点?

最佳答案

您必须在groupbyl1列上使用l2,因为您想根据x列的值的变化来比较这两个值(l1, l2)对的t列的差异。
默认情况下,diff计算按t=1分组的(t=0)和(l1 & l2)的值之间的差异,并返回结果所以,如果你想找出(x)和(t=2)之间t=0值的差异,你只需要做diff(periods=2)
最后,使用tranform方法返回组块的每个组中计算出的差异。

In [3]: df['delta_x'] = df.groupby(['l1', 'l2'])['x'].transform(lambda x: x.diff())

In [4]: df
Out[4]:
    t  l1   l2    x  delta_x
0   0   3   10    0      NaN
1   0   3  100    0      NaN
2   0   4   10    0      NaN
3   0   4  100    0      NaN
4   1   3   10   14     14.0
5   1   3  100  104    104.0
6   1   4   10   15     15.0
7   1   4  100  105    105.0
8   2   3   10   28     14.0
9   2   3  100  208    104.0
10  2   4   10   30     15.0
11  2   4  100  210    105.0

时间限制:
In [5]: %timeit df['delta_x'] = df.groupby(['l1', 'l2'])['x'].transform(lambda x: x.diff())
1000 loops, best of 3: 1.55 ms per loop

In [17]: %timeit df['delta_x'] = df.x - df.merge(df, left_on=['t', 'l1', 'l2'], right_on=['t.1', 'l1', 'l2'],how='left',suffixes=['','.1'])['x.1']
100 loops, best of 3: 3.33 ms per loop

07-26 07:01