2013-05-06 78 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