如何获得最后N行RELATIVE到pandas中的另一行(向量解决方案)?

时间:2014-09-08 12:15:43

标签: python pandas dataframe

我已经在另一个更长的问题的背景下问过这个问题,但我想我曾试图同时提出太多问题。所以,为简单起见:

我有一个数据框,每次试用都会按下一个键。我想添加一个显示最后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   

之后它看起来像这样(对于每一个人):

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]

这是否有矢量化解决方案?我似乎无法弄清楚如何选择相对行。 (熊猫新手 - 不是那么想这个方式,但是)

更新:根据以下贡献者的建议,我最终做到了这一点:

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 :(得分:2)

一种方法是使用shift将相关列向下移动n行,然后连接条目(它们是字符串,以便我们可以使用+):

df.last_3 = df.key_pressed.shift(1) + ', ' + df.key_pressed.shift(2) + ', ' + df.key_pressed.shift(3)

这将创建前三个条目的字符串,用逗号和空格(不是列表)分隔。如果可能的话,我会避免在DataFrame中使用列表,因为事情会变得有些混乱。

答案 1 :(得分:1)

你想对这些名单做什么?在Series / DataFrames中存储列表通常不是很方便。无论如何,这会让你接近。你必须处理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自动获取列表并将其重新转换为系列。试试这个,你会明白为什么它不起作用:

pd.concat([df.key_pressed.shift(i) for i in [0, 1, 2]], 1).apply(list, 1)

答案 2 :(得分:0)

哦 - 也许这是最好的解决方案。人们可以将数据“转移”一定数量:

df['shifted'] = df.groupby('sid')['key_pressed'].shift(2)

然后我可以根据这些转移的数据创建列表。

答案 3 :(得分: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