Pandas 数据透视表嵌套排序
Posted
技术标签:
【中文标题】Pandas 数据透视表嵌套排序【英文标题】:Pandas pivot table Nested Sorting 【发布时间】:2016-09-05 23:31:40 【问题描述】:鉴于此数据框和数据透视表:
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
提前致谢!
【问题讨论】:
z, x, y
未按任何顺序排序。
嗨,亚历山大。是的,那是因为我希望能够自定义排序第一个索引的顺序。
【参考方案1】:
我认为没有一种简单的方法可以实现您的目标。以下解决方案首先根据列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
【讨论】:
非常好。 :) 我尝试按字典映射,但这更好。【参考方案2】:解决方案
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=0
和 level=0
如果您想进一步利用它,可能对您很重要。但是,这些也是默认值,可以省略。
drop_level=False
是这里的关键参数,并且对于保持 idx_v
是必要的,我们正在采用 xs
以便 pd.concat
以我们想要的方式将它们组合在一起。
我在 pd.concat
调用中以与 Alexander 几乎完全相同的方式使用列表推导式。
演示
print new_table
A B
z two 6
one 3
x one 7
two 4
y one 5
two 1
Name: C, dtype: int64
【讨论】:
【参考方案3】:如果您可以在 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)
【讨论】:
我似乎无法实现你提到的。 我已经用另一种方式编辑了我的答案以转换为分类数据。我假设这是您无法实现的部分? 谢谢,@root!这对我来说很清楚。出于好奇,我看到另一种方法是 df['A'] = df['A'].astype('category') 然后在下一行 df['A'].cat.set_categories( ['z','x','y'],inplace=True) 在某些情况下,一种方法是否比另一种更好? 我不太了解 pandas 如何实现分类数据来判断一种方法是否比另一种更好。为了简洁起见,我更喜欢在一行中完成所有操作,但这纯粹是个人风格。 我发现这个答案很有用并且被赞成。但是,使用 Pandas 1.0.1astype
似乎不接受类别参数。我得到:TypeError: astype() got an unexpected keyword argument 'categories'
。我能够使用 CategoricalDtype (from pandas.api.types import CategoricalDtype
) 做到这一点。然后cat_type = CategoricalDtype(categories=my_ordered_list,ordered=True)
和df.astype(cat_type)
,根据docs.以上是关于Pandas 数据透视表嵌套排序的主要内容,如果未能解决你的问题,请参考以下文章
Python:在 python 中重现嵌套的 Excel 数据透视表
快速入门pandas进行数据挖掘数据分析[多维度排序数据筛选分组计算透视表]
快速入门pandas进行数据挖掘数据分析[多维度排序数据筛选分组计算透视表]