2016-05-10 82 views
2

鑑於這種數據幀和樞軸表:熊貓透視表嵌套排序

import pandas as pd 
df=pd.DataFrame({'A':['x','y','z','x','y','z'], 
       'B':['one','one','one','two','two','two'], 
       'C':[7,5,3,4,1,6]}) 
df 


    A B  C 
0 x one  7 
1 y one  5 
2 z one  3 
3 x two  4 
4 y two  1 
5 z two  6 

table = pd.pivot_table(df, index=['A', 'B'],aggfunc=np.sum) 

table 
A B 
x one 7 
    two 4 
y one 5 
    two 1 
z one 3 
    two 6 
Name: C, dtype: int64 

我要排序的透視表,使得「A」的順序是Z,X,Y和B」的順序'基於數據幀列'C'中遞減排序的值。

像這樣:

A B 
z two 6 
    one 3 
x one 7 
    two 4 
y one 5 
    two 1 

    Name: C, dtype: int64 

提前感謝!

+0

z,x ,y'沒有按任何順序排序。 – Alexander

+0

嗨亞歷山大。是的,那是因爲我想能夠自定義排序第一個索引的順序。 –

回答

2

我不相信有一個簡單的方法來實現你的目標。以下解決方案首先根據列C的值對數據表進行降序排序。然後根據您所需的順序連接每個切片。

order = ['z', 'x', 'y'] 
table = table.reset_index().sort_values('C', ascending=False) 
>>> pd.concat([table.loc[table.A == val, :].set_index(['A', 'B']) for val in order]) 
     C 
A B  
z two 6 
    one 3 
x one 7 
    two 4 
y one 5 
    two 1 
+1

非常好。 :)我嘗試用字典來映射,但這樣更好。 – jezrael

1

解決方案

custom_order = ['z', 'x', 'y'] 
kwargs = dict(axis=0, level=0, drop_level=False) 

new_table = pd.concat(
    [table.xs(idx_v, **kwargs).sort_values(ascending=False) for idx_v in custom_order] 
) 

替代一個襯墊

pd.concat([table.xs(i, drop_level=0).sort_values(ascending=0) for i in list('zxy')] 

說明

custom_order是你希望的順序。 kwargs是一種提高可讀性的方便方法(在我看來)。要注意的要點,axis=0level=0對您而言可能很重要,如果您想進一步利用此功能。但是,這些也是默認值,可以省略。 drop_level=False是這裏的關鍵參數,並且必須保持idx_v我們正在採取xs,以便pd.concat以我們想要的方式將它們放在一起。

我在pd.concat調用中以幾乎完全相同的方式使用列表理解。

示範

print new_table 

A B 
z two 6 
    one 3 
x one 7 
    two 4 
y one 5 
    two 1 
Name: C, dtype: int64 
1

如果你能在A列的分類數據看,那麼它變得更加簡單。將您的類別設置爲list('zxy')並指定ordered=True將使用您的自定義順序。

您可以使用類似的東西在你的數據讀取:

'A':pd.Categorical(['x','y','z','x','y','z'], list('zxy'), ordered=True) 

或者,也可以在數據讀出您當前所在,然後用astype至A轉換成範疇:

df['A'] = df['A'].astype('category', categories=list('zxy'), ordered=True) 

一旦A是分類,您可以像以前一樣樞軸轉動,然後按以下順序排列:

table = table.sort_values(ascending=False).sortlevel(0, sort_remaining=False) 
+0

我似乎無法實現您提到的內容。 –

+1

我用另一種方式編輯了我的答案,以轉換爲分類數據。我假設那是你不能實現的部分? – root

+0

謝謝,@root!這爲我澄清了它。出於好奇,我看到另一種做法是在下一行df ['A'] = df ['A']。astype('category')df ['A']。cat.set_categories( ['z','x','y'],inplace = True)在某些情況下,一種方法比另一種更好嗎? –