是否可以按每组的和的计数值进行排序?不突破指数水平?我注释掉的两次尝试都会排序,但会破坏索引级别。
#DataFrame
ff = pd.DataFrame([('P1', 17, 'male'),
('P2', 10, 'female'),
('P3', 10, 'male'),
('P4', 19, 'female'),
('P5', 10, 'male'),
('P6', 12, 'male'),
('P7', 12, 'male'),
('P8', 15, 'female'),
('P9', 15, 'female'),
('P10', 10, 'male')],
columns=['Name', 'Age', 'Sex'])
# Attempts
(
ff
.groupby(['Age', 'Sex'])
.agg(**{
'Count': pd.NamedAgg(column="Name", aggfunc='count'),
'Who': pd.NamedAgg(column="Name", aggfunc=lambda x: ', '.join([i for i in x]))})
# .sort_values('Count') <- this breaks the index level
# .sort_values(['Count', 'Age']) <- this too breaks the index level
)
原始数据:
可以通过DataFrame.unstack
重塑,如果存在,则通过Sex
值之和排序索引,然后通过DataFrame.stack
重塑:
df1 = df.unstack()
df1 = df1.sort_index(key=df1.sum(axis=1, numeric_only=True).get).stack().astype(df.dtypes)
print (df1)
Count Who
Age Sex
17 male 1 P1
19 female 1 P4
12 male 2 P6, P7
15 female 2 P8, P9
10 female 1 P2
male 3 P3, P5, P10
另一个想法是用GroupBy.transform
对两个值求和:
df['tmp'] = df.groupby('Age')['Count'].transform('sum')
df1 = df.sort_values(['tmp','Age']).drop('tmp', axis=1)
print (df1)
Count Who
Age Sex
17 male 1 P1
19 female 1 P4
12 male 2 P6, P7
15 female 2 P8, P9
10 female 1 P2
male 3 P3, P5, P10
编辑:一行解决方案是:
df = (
ff
.groupby(['Age', 'Sex'])
.agg(**{
'Count': pd.NamedAgg(column="Name", aggfunc='count'),
'Who': pd.NamedAgg(column="Name", aggfunc=', '.join)})
.assign(tmp = lambda x: x.groupby('Age')['Count'].transform('sum'))
.sort_values(['tmp','Age'])
.drop('tmp', axis=1))
print (df)
Count Who
Age Sex
17 male 1 P1
19 female 1 P4
12 male 2 P6, P7
15 female 2 P8, P9
10 female 1 P2
male 3 P3, P5, P10
好了。
让我们将temp变量保留在data
中。
data = ff.groupby(['Age', 'Sex']).agg(**{
'Count': pd.NamedAgg(column="Name", aggfunc='count'),
'Who': pd.NamedAgg(column="Name", aggfunc=lambda x: ', '.join([i for i in x]))})
您可以通过apply
函数在每个组中编写一个自定义函数来做您想做的事情。
例如。
data.groupby("Age", group_keys=False).apply(lambda x: x.sort_values("Count", ascending=False))
Count Who
Age Sex
10 male 3 P3, P5, P10
female 1 P2
12 male 2 P6, P7
15 female 2 P8, P9
17 male 1 P1
19 female 1 P4
或者改成ascending order
data.groupby("Age", group_keys=False).apply(lambda x: x.sort_values("Count", ascending=False))
Count Who
Age Sex
10 female 1 P2
male 3 P3, P5, P10
12 male 2 P6, P7
15 female 2 P8, P9
17 male 1 P1
19 female 1 P4
或者如果你想按每一级多索引排序。你可以这样做。
您可以通过在sort_index
函数中添加level
参数来对索引进行排序。
例如:
data.sort_index(level=0, ascending=True)
对第一个索引按升序排序。
Count Who
Age Sex
19 female 1 P4
17 male 1 P1
15 female 2 P8, P9
12 male 2 P6, P7
10 male 3 P3, P5, P10
female 1 P2
data.sort_index(level=[0,1], ascending=[False, True])
第一个索引按升序排序,第二个索引按降序排序。
Count Who
Age Sex
19 female 1 P4
17 male 1 P1
15 female 2 P8, P9
12 male 2 P6, P7
10 female 1 P2
male 3 P3, P5, P10
顺便说一下。
breaking index level
不是一个特殊的结果。它只是一个显示优化
例如。
你可以自己创建一个:
pd.DataFrame({"a":[1,2,3,4,5]}, index=pd.MultiIndex.from_arrays([[10,10,20,10,10],['F','M','F','M','F']],names=['A','B']))
a
A B
10 F 1
M 2
20 F 3
10 M 4
F 5