Itertools:根据前三行或列表中的前一个元素选择pandas

时间:2014-09-07 23:17:00

标签: python pandas itertools

希望能帮助解决一整天困扰我的问题。我有一个实验数据,通过屏幕要求主题按下键盘上的四个按钮之一 - ' m'' x'' n' ,' z' - 进行1600次试验。在偶数试验中,按钮按下服从随机选择的图案(例如mnzxmnzxmnzx),但在奇数试验中,按下按钮是随机选择的。我给出的数据集仅包含受试者在哪个试验中按哪个键。我需要找出:

(1)主题的模式是什么。 (我试过这个,因为模式重复了)

def find_pattern(df):
'''find the pattern for this subject'''
   criterion = df['trial'].isin([1, 3, 5, 7])
   the_pattern = df[criterion].circle_key.tolist()
   return df


df = df.groupby('sid').apply(find_pattern)

(2)找出这个主题模式的可能组合(即如果我按下“下一个模式元素将是' x')

为此我尝试了一堆不同的itertools,但没有一个完全符合我的要求。我想基本上采取这个清单:

 ['m', 'x', 'z', 'n'] 

我得到的每一个(1)并完成两个IN ORDER的所有可能组合。所以这将是:

 [('m', 'x'), ('x', 'z'), ('z', 'n'), ('n', 'm')]

没有其他可能性。然后,我想创建一个列,在最后三次试验(包括当前试验)中生成三联体,如下面的triplet栏所示。我觉得必须有某种滚动窗口,或者简单的方法选择最后三次试验。我已经尝试了各种错误的东西 - 我似乎无法弄清楚如何引用"当前"数据框中的行(不使用for列表)...

我需要这些值,因为我需要比较triplet的第一个和最后一个元素是否是可能的组合之一(possible_comb)。 (因此对于试验3,答案是正确的,而试验4答案是假的)。

非常感谢任何帮助。我目前的数据如下:

trial sid key
1     1   'm'
2     1   'm'  
3     1   'x'
4     1   'n'
5     1   'x'
6     1   'x'
7     1   'n'
1     2   'm'
2     2   'm'
...   ... 

我希望它看起来像这样:

trial sid key    pattern               possible_comb                                 triplet
1     1   'm'    ['m', 'x', 'x', 'n']  [('m','x'), ('x','x'), ('x','n'), ('n', 'm')] NaN
2     1   'm'    ['m', 'x', 'x', 'n']  [('m','x'), ('x','x'), ('x','n'), ('n', 'm')] NaN
3     1   'x'    ['m', 'x', 'x', 'n']  [('m','x'), ('x','x'), ('x','n'), ('n', 'm')] ['m', 'm', 'x']
4     1   'n'    ['m', 'x', 'x', 'n']  [('m','x'), ('x','x'), ('x','n'), ('n', 'm')] ['m', 'x', 'n']
5     1   'x'    ['m', 'x', 'x', 'n']  [('m','x'), ('x','x'), ('x','n'), ('n', 'm')] ['x', 'n', 'x']
6     1   'x'    ['m', 'x', 'x', 'n']  [('m','x'), ('x','x'), ('x','n'), ('n', 'm')] ['n', 'x', 'x'] 
7     1   'n'    ['m', 'x', 'x', 'n']  [('m','x'), ('x','x'), ('x','n'), ('n', 'm')] ['x', 'x', 'n']
1     2   'n'    ['n', 'x', 'm', 'n']  [('m','x'), ('x','x'), ('x','n'), ('n', 'm')] NaN
2     2   'm'    ['n', 'x', 'm', 'n']  [('m','x'), ('x','x'), ('x','n'), ('n', 'm')] NaN
...   ... 

1 个答案:

答案 0 :(得分:2)

要获得“模式”,您只需要对主题ID进行分组并采用其他所有元素。可以这样做:

>>> d.groupby('sid')['key'].apply(lambda c: list(c[::2]))
sid
1      ['m', 'x', 'x', 'n']

(我将你的例子截断为只包含一个主题,因为你只包含来自主题2的部分数据,这个数据太短而不具有“模式”。所以这是主题1的模式。)

如果要在相应主题的原始DataFrame的每一行中复制该数据,请使用map获取每个主题ID的模式:

>>> d['pattern'] = d.sid.map(d.groupby('sid')['key'].apply(lambda c: list(c[::2])))
>>> d
   trial  sid  key               pattern
0      1    1  'm'  ['m', 'x', 'x', 'n']
1      2    1  'm'  ['m', 'x', 'x', 'n']
2      3    1  'x'  ['m', 'x', 'x', 'n']
3      4    1  'n'  ['m', 'x', 'x', 'n']
4      5    1  'x'  ['m', 'x', 'x', 'n']
5      6    1  'x'  ['m', 'x', 'x', 'n']
6      7    1  'n'  ['m', 'x', 'x', 'n']

要获得顺序组合,您只需将第一个元素添加到末尾(以便序列“循环”),然后通过抓取两个元素的子列表来提取组合,使用如下函数:

def getCombs(pattern):
    pattern = pattern + [pattern[0]]
    return [pattern[ix:ix+2] for ix in xrange(len(pattern)-1)]

然后你可以将模式放到你的DataFrame中:

>>> d['combs'] = d.pattern.map(getCombs)
>>> d.combs
0    [['m', 'x'], ['x', 'x'], ['x', 'n'], ['n', 'm']]
1    [['m', 'x'], ['x', 'x'], ['x', 'n'], ['n', 'm']]
2    [['m', 'x'], ['x', 'x'], ['x', 'n'], ['n', 'm']]
3    [['m', 'x'], ['x', 'x'], ['x', 'n'], ['n', 'm']]
4    [['m', 'x'], ['x', 'x'], ['x', 'n'], ['n', 'm']]
5    [['m', 'x'], ['x', 'x'], ['x', 'n'], ['n', 'm']]
6    [['m', 'x'], ['x', 'x'], ['x', 'n'], ['n', 'm']]
Name: combs, dtype: object

(我这里只显示“梳子”列,因为包括所有列使得它太宽而无法显示。)