Is it possible to sort values by the count values of each group's sum. without breaking the index level? Both attempts I commented out would sort but breaks the index level.
#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
)
Original Data:
| 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 |
Desired Output: (sort values by the sum of 'Age' group, but keep the grouped index)
| 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 |
Edit: This is how I finally solve the problem, any more advices are appreciated.
# DataFrame -- I update a bit for testcases.
ff = pd.DataFrame([('P1', 19, 'male'),
('P2', 10, 'female'),
('P3', 10, 'male'),
('P4', 19, 'female'),
('P5', 10, 'male'),
('P6', 12, 'male'),
('P7', 12, 'male'),
('P7', 12, 'male'),
('P7', 12, 'male'),
('P7', 12, 'male'),
('P8', 15, 'female'),
('P9', 15, 'female'),
('P10', 10, 'male')],
columns=['Name', 'Age', 'Sex'])
# It works !
(
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 by 'Count' and keep the group adding 'tmp'
.assign(
tmp=lambda x: x.reset_index().groupby('Age')['Count'].transform('sum').to_numpy())
.sort_values(['tmp','Age'])
# drop tmp
.drop('tmp', axis=1)
)