2016-05-10 86 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)在某些情况下,一种方法比另一种更好吗? –