2016-11-23 145 views
1

我在下面的示例表格之後的熊貓數據幀創建透視數據框:使用多列在熊貓

data = {'id': [1,1,1,1,2,2,2,2,3,3,3], 'a': [-1,1,1,0,0,0,-1,1,-1,0,0], 'b': [1,0,0,-1,0,1,1,-1,-1,1,0]} 
df = pd.DataFrame(data) 

現在,我想要做的就是創建一個數據透視表,使得對於每一列除了id之外,我將有3個新的列對應於這些值。也就是說,對於列a,我將創建a_neg,a_zeroa_pos。同樣,對於b,我將創建b_neg,b_zerob_pos。這些新列的值將與這些值在原始ab列中出現的次數相對應。最終的數據幀應該是這樣的:

result = {'id': [1,2,3], 'a_neg': [1, 1, 1], 
     'a_zero': [1, 2, 2], 'a_pos': [2, 1, 0], 
     'b_neg': [1, 1, 1], 'b_zero': [2,1,1], 'b_pos': [1,2,1]} 
df_result = pd.DataFrame(result) 

現在,要做到這一點,我可以做下面的步驟,在我最後得出答案:

by_a = df.groupby(['id', 'a']).count().reset_index().pivot('id', 'a', 'b').fillna(0).astype(int) 
by_a.columns = ['a_neg', 'a_zero', 'a_pos'] 

by_b = df.groupby(['id', 'b']).count().reset_index().pivot('id', 'b', 'a').fillna(0).astype(int) 
by_b.columns = ['b_neg', 'b_zero', 'b_pos'] 

df_result = by_a.join(by_b).reset_index() 

但是,我認爲,這種方法是不特別是如果我有很多原始列除了ab。有沒有更短的和/或更有效的解決方案來獲得我想要達到的目標?謝謝。

回答

0

較短的解決方案,但還是相當的高效:

In [11]: df1 = df.set_index("id") 

In [12]: g = df1.groupby(level=0) 

In [13]: g.apply(lambda x: x.apply(lambda x: x.value_counts())).fillna(0).astype(int).unstack(1) 
Out[13]: 
    a  b 
    -1 0 1 -1 0 1 
id 
1 1 1 2 1 2 1 
2 1 2 1 1 1 2 
3 1 2 0 1 1 1 

注:我想你應該瞄準的多指標列。


我有理由相信我已經看到了一招,去掉的東西更清潔,更高效的施加/ VALUE_COUNT/fillna,但此刻它躲開我......