如何在pandas中获取相对另一行的最后N行(向量解)?
我之前在一个更长的问题中提过这个问题,但我觉得我一次问了太多东西。所以,为了简单明了:
我有一个数据框,每次试验都会按下一个键。我想添加一列,显示最后 N 行的数据。所以如果我的数据看起来像这样:
trial sid key_pressed RT
1 S04 x 0.502242
2 S04 m 0.348620
3 S04 m 0.312491
4 S04 x 0.342541
5 S04 n 0.419384
6 S04 n 0.348211
7 S04 z 0.376369
那么每个单独的 sid 之后会变成这样:
trial sid key_pressed RT last_3
1 S04 x 0.502242 NaN
2 S04 m 0.348620 NaN
3 S04 m 0.312491 [x, m, m]
4 S04 x 0.342541 [m, m, x]
5 S04 n 0.419384 [m, x, n]
6 S04 n 0.348211 [x, n, n]
7 S04 z 0.376369 [n, n, z]
有没有什么快速的方法可以做到这一点?我似乎无法弄清楚如何选择相对的行。(我刚接触 pandas,还不太习惯这样思考)
更新:根据下面贡献者的建议,我最终做了这个:
df['shifted'] = pd.concat([df.groupby('sid')['key_pressed'].shift(2) + df.groupby('sid')['key_pressed'].shift(1) + df.groupby('sid')['key_pressed'].shift(0)])
这创建了一个字符串 mxm
,比如说。这样更好。
4 个回答
0
哦,也许这就是最好的解决办法。我们可以把数据“移动”一个特定的数量:
df['shifted'] = df.groupby('sid')['key_pressed'].shift(2)
然后我就可以根据这个移动后的数据来创建列表。
0
这个解决方案避免了循环,但我不太确定这是否真的算是“向量化”,因为一旦你开始使用 apply()
这个函数,我觉得你就会失去向量化带来的性能优势。
key_table = pd.concat(
[df.key_pressed.shift(2), df.key_pressed.shift(1), df.key_pressed],
axis=1
)
df['last_3'] = key_table.apply(
lambda row: ', '.join(str(k) for k in row),
axis=1
)
输出结果:
trial sid key_pressed RT last_3
0 1 S04 x 0.502242 nan, nan, x
1 2 S04 m 0.348620 nan, x, m
2 3 S04 m 0.312491 x, m, m
3 4 S04 x 0.342541 m, m, x
4 5 S04 n 0.419384 m, x, n
5 6 S04 n 0.348211 x, n, n
6 7 S04 z 0.376369 n, n, z
1
你想用这些列表做什么呢?把列表放在Series或DataFrame里面通常不是很方便。不过,这样做可以让你接近目标。你需要处理一下nans
,然后就完成了。
In [6]: pd.concat([df.key_pressed.shift(i) for i in [0, 1, 2]], 1).apply(tuple, 1).map(list)
Out[6]:
0 [x, nan, nan]
1 [m, x, nan]
2 [m, m, x]
3 [x, m, m]
4 [n, x, m]
5 [n, n, x]
6 [z, n, n]
dtype: object
注意,我们需要先把列表转换成元组,然后再转换成列表,这样才能避免pandas自动把我们的列表变回Series。试试这个,你就会明白为什么这样不行了:
pd.concat([df.key_pressed.shift(i) for i in [0, 1, 2]], 1).apply(list, 1)
2
一种方法是使用 shift
函数,把相关的列向下移动 n
行,然后把这些条目连接起来(因为它们是字符串,所以可以用 +
来连接):
df.last_3 = df.key_pressed.shift(1) + ', ' + df.key_pressed.shift(2) + ', ' + df.key_pressed.shift(3)
这样就会生成由前面三个条目组成的字符串,中间用逗号和空格隔开(而不是列表)。如果可以的话,我建议在数据框中尽量避免使用列表,因为那样会让事情变得有点复杂。