Pandas pivot table Nested Sorting

久未见 提交于 2019-11-29 15:38:58

I don't believe there is an easy way to accomplish your objective. The following solution first sorts your table is descending order based on the values of column C. It then concatenates each slice based on your desired order.

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

Solution

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]
)

Alternate one liner

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

Explanation

custom_order is your desired order. kwargs is a convenient way to improve readability (in my opinion). Key elements to note, axis=0 and level=0 might be important for you if you want to leverage this further. However, those are also the default values and can be left out. drop_level=False is the key argument here and is necessary to keep the idx_v we are taking a xs of such that the pd.concat puts it all together in the way we'd like.

I use a list comprehension in almost the exact same manner as Alexander within the pd.concat call.

Demonstration

print new_table

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

If you can read in column A as categorical data, then it becomes much more straightforward. Setting your categories as list('zxy') and specifying ordered=True uses your custom ordering.

You can read in your data using something similar to:

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

Alternatively, you can read in the data as you currently are, then use astype to convert A to categorical:

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

Once A is categorical, you can pivot the same as before, and then sort with:

table = table.sort_values(ascending=False).sortlevel(0, sort_remaining=False)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!