Pandas pivot table 嵌套排序
Pandas pivot table Nested Sorting
给定这个数据框和枢轴 table:
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
我想对主元 table 进行排序,使得 '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
提前致谢!
我认为没有简单的方法可以完成您的 objective。以下解决方案首先根据列 C
的值对 table 进行降序排序。然后它会根据您想要的顺序连接每个切片。
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
解决方案
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
调用中使用列表理解的方式几乎与亚历山大完全相同。
示范[=26=]
print new_table
A B
z two 6
one 3
x one 7
two 4
y one 5
two 1
Name: C, dtype: int64
如果您可以在 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)
给定这个数据框和枢轴 table:
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
我想对主元 table 进行排序,使得 '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
提前致谢!
我认为没有简单的方法可以完成您的 objective。以下解决方案首先根据列 C
的值对 table 进行降序排序。然后它会根据您想要的顺序连接每个切片。
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
解决方案
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
调用中使用列表理解的方式几乎与亚历山大完全相同。
示范[=26=]
print new_table
A B
z two 6
one 3
x one 7
two 4
y one 5
two 1
Name: C, dtype: int64
print new_table
A B
z two 6
one 3
x one 7
two 4
y one 5
two 1
Name: C, dtype: int64
如果您可以在 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)