Itertools:基于前3行或列表中前几个元素在Pandas中选择
我今天遇到一个问题,希望能得到一些帮助。我的实验数据是这样的:参与者在屏幕上被要求按下键盘上的四个按钮之一——'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) 找出这个参与者模式的所有可能组合(也就是说,如果我按了'm',那么下一个模式的元素会是'x')
为此,我尝试了很多不同的itertools,但没有一个完全符合我的要求。我基本上想要从列表中:
['m', 'x', 'z', 'n']
对我在(1)中得到的每一个元素,进行所有可能的两个元素的组合,并且要保持顺序。所以这将是:
[('m', 'x'), ('x', 'z'), ('z', 'n'), ('n', 'm')]
而且没有其他可能性。接下来,我想创建一列,把最近三次试验的结果(包括当前这一试验)组合成一个三元组,就像下面的triplet
列那样。我觉得应该有某种滚动窗口,或者简单的方法来选择最近的三次试验。我尝试了各种错误的方法——我似乎无法弄清楚如何在数据框中引用“当前”这一行(不使用for
列表)……
我需要这些值,因为我想比较triplet
的第一个和最后一个元素是否是可能组合之一(possible_comb
)。所以对于第3次试验,答案应该是TRUE,而第4次试验的答案应该是FALSE。
任何帮助都将非常感激。我的当前数据看起来是这样的:
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 个回答
要获取“模式”,你只需要根据主题ID进行分组,然后取每隔一个的元素。可以用下面这个方法来实现:
>>> d.groupby('sid')['key'].apply(lambda c: list(c[::2]))
sid
1 ['m', 'x', 'x', 'n']
(我把你的例子简化了,只保留了一个主题,因为你只提供了主题2的部分数据,而那部分数据太短,无法形成一个“模式”。所以这里是主题1的模式。)
如果你想把这个数据复制到原始数据表中对应主题的每一行,可以使用 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)]
然后你就可以把这些模式放入你的数据表中:
>>> 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
(这里我只显示“combs”这一列,因为如果显示所有列会让表格太宽,不方便查看。)