2013-05-06 85 views
2

我的数据包含类似于此的结构(减少到2层的元件,但也有十位):熊猫:提取物和选择数据从列使用图案

Variable  elem_1_pre elem_1_post elem_2_pre elem_2_post 
Observation1 present  absent  absent  present 
Observation2 absent  present  present  absent 

的最终目标是选择观测(和可能还有相关的列名),它们出现在pre中,但在post中不存在,反之亦然。

换句话说,像(伪)

("present" in *_pre and "absent" in *_post) or 
("present" in *_post and "absent" in *_pre) 

我想groupby的操作可以用于此。熊猫有这种可能吗?

回答

1

如果您的数据框的值是完全相同的字符串'present''absent',那么你可以将字符串值转换为布尔值与

In [17]: df.values == 'present' 
Out[17]: 
array([[ True, False, False, True], 
     [False, True, True, False]], dtype=bool) 

一旦你有了布尔值,你可以使用NumPy的XOR逻辑运算符,^,两列组合成所需的值:

import pandas as pd 
df = pd.DataFrame(['present absent absent present'.split(), 
        'absent present present absent'.split()], 
        columns='elem_1_pre elem_1_post elem_2_pre elem_2_post'.split(), 
        index='Observation1 Observation2'.split(),) 
df = pd.DataFrame(df.values == 'present', 
        columns=df.columns, 
        index=df.index) 
print(df) 
#    elem_1_pre elem_1_post elem_2_pre elem_2_post 
# Observation1  True  False  False  True 
# Observation2  False  True  True  False 

for i in range(1,3): 
    elem = ['elem_{i}_{s}'.format(i=i, s=suf) for suf in ('pre', 'post')] 
    change = 'elem_{i}_change'.format(i=i) 
    df[change] = df[elem[0]]^df[elem[1]] 
print(df.ix[:, 'elem_1_change elem_2_change'.split()]) 

产生

   elem_1_change elem_2_change 
Observation1   True   True 
Observation2   True   True 
+0

他们这些人恰恰是因为我建源DataaFrame,所以我会放弃这一点。谢谢 – Einar 2013-05-06 09:58:02

2

你想知道groupby是否可以在这里使用,所以我会提到它是如何的。短版,虽然我可能会写这两条线为清楚:

(df == 'present').groupby(lambda x: x.rsplit("_", 1)[0], axis=1).sum() == 1 

首先,我们可以从一个例子开始数据帧,@unutbu致意(注:这是你们的不同,所以输出是不是所有的真):

>>> import pandas as pd 
>>> df = pd.DataFrame(['present absent absent absent'.split(), 
        'present present present absent'.split()], 
        columns='elem_1_pre elem_1_post elem_2_pre elem_2_post'.split(), 
        index='Observation1 Observation2'.split(),) 
>>> df 
      elem_1_pre elem_1_post elem_2_pre elem_2_post 
Observation1 present  absent  absent  absent 
Observation2 present  present present  absent 

我们可以判断哪些是present

>>> p = df == "present" 
>>> p 
      elem_1_pre elem_1_post elem_2_pre elem_2_post 
Observation1  True  False  False  False 
Observation2  True  True  True  False 

然后,我们真正想要做的是将列分组到“elem_1”位。您可以使用字符串方法或正则表达式,或者如果它们是有序的,则可以使用索我喜欢使用字符串方法,因此我们将右侧的第一个_分隔列名称。要通过列组,我们使用axis=1

>>> for k, g in p.groupby(lambda x: x.rsplit("_", 1)[0], axis=1): 
    print 'group key:', k 
    print g 
...  
group key: elem_1 
      elem_1_pre elem_1_post 
Observation1  True  False 
Observation2  True  True 
group key: elem_2 
      elem_2_pre elem_2_post 
Observation1  False  False 
Observation2  True  False 

我们想算成一排的真值,看看是否有只有一个。真〜1和False〜0,所以我们可以使用sum

>>> p.groupby(lambda x: x.rsplit("_", 1)[0], axis=1).sum() 
       elem_1 elem_2 
Observation1  1  0 
Observation2  2  1 

然后

>>> p.groupby(lambda x: x.rsplit("_", 1)[0], axis=1).sum() == 1 
      elem_1 elem_2 
Observation1 True False 
Observation2 False True 

或者,把他们放在一起:

>>> grouped = (df == "present").groupby(lambda x: x.rsplit("_", 1)[0], axis=1) 
>>> answer = grouped.sum() == 1 
>>> answer 
      elem_1 elem_2 
Observation1 True False 
Observation2 False True