Cómo ordenar la tabla dinámica en Pandas

Aquí está el código:

test = pd.DataFrame({'country':['us','ca','ru','cn','ru','cn','us','ca','ru','cn','us','ca','ru','cn','us','ca'], 'month':[5,6,7,5,6,7,5,5,6,7,5,6,6,5,5,6], 'id':[x for x in range(16)]}) p = test.pivot_table(index=['month', 'country'], aggfunc='count')[['id']] 

La salida se ve así:

introduzca la descripción de la imagen aquí

Me gustaría ordenar la tabla por la columna de id , para que el número más grande aparezca en la parte superior como:

  id month country us 4 5 cn 2 ca 1 

Necesita DataFrame.reset_index , DataFrame.sort_values y DataFrame.set_index :

 p1 = p.reset_index() .sort_values(['month','id'], ascending=[1,0]) .set_index(['month','country']) print (p1) id month country 5 us 4 cn 2 ca 1 6 ca 3 ru 3 7 cn 2 ru 1 

Porque esta solución no funciona 🙁

 p1 = p.sort_index(level='month', sort_remaining=True) \ .sort_values('id', ascending=False) print (p1) id month country 5 us 4 6 ca 3 ru 3 5 cn 2 7 cn 2 5 ca 1 7 ru 1 

Opción 1
Esto se ordena por id dentro de los grupos definidos por el nivel de month dentro del índice.

 p.groupby( level='month', group_keys=False ).apply(pd.DataFrame.sort_values, by='id', ascending=False) id month country 5 us 4 cn 2 ca 1 6 ca 3 ru 3 7 cn 2 ru 1 

opcion 2
Este primero ordena todo el dataframe por id luego se ordena nuevamente por nivel de month dentro del índice. Sin embargo, tuve que usar sort_remaining=False por razones que se explican por sí mismas y kind='mergesort' porque mergesort es una clasificación estable y no se metirá con el orden preexistente dentro de los grupos definidos por el nivel ‘month’.

 p.sort_values('id', ascending=False) \ .sort_index(level='month', sort_remaining=False, kind='mergesort') id month country 5 us 4 cn 2 ca 1 6 ca 3 ru 3 7 cn 2 ru 1 

Opcion 3
Esto usa el lexsort de lexsort … esto funciona, pero no me gusta porque depende de que la id sea ​​numérica y de que pueda poner un negativo delante de ella para obtener un orden descendente. /encogimiento de hombros

 p.iloc[np.lexsort([-p.id.values, p.index.get_level_values('month')])] id month country 5 us 4 cn 2 ca 1 6 ca 3 ru 3 7 cn 2 ru 1