¿Cómo ordenar un dataFrame en python pandas por dos o más columnas?

Respuestas:

454

A partir de la versión 0.17.0, el sortmétodo fue desaprobado a favor de sort_values. sortse eliminó por completo en la versión 0.20.0. Los argumentos (y resultados) siguen siendo los mismos:

df.sort_values(['a', 'b'], ascending=[True, False])

Puede usar el argumento ascendente de sort:

df.sort(['a', 'b'], ascending=[True, False])

Por ejemplo:

In [11]: df1 = pd.DataFrame(np.random.randint(1, 5, (10,2)), columns=['a','b'])

In [12]: df1.sort(['a', 'b'], ascending=[True, False])
Out[12]:
   a  b
2  1  4
7  1  3
1  1  2
3  1  2
4  3  2
6  4  4
0  4  3
9  4  3
5  4  1
8  4  1

Como comentó @renadeen

Ordenar no está en su lugar por defecto! Por lo tanto, debe asignar el resultado del método de clasificación a una variable o agregar inplace = True a la llamada al método.

es decir, si desea reutilizar df1 como un DataFrame ordenado:

df1 = df1.sort(['a', 'b'], ascending=[True, False])

o

df1.sort(['a', 'b'], ascending=[True, False], inplace=True)
Andy Hayden
fuente
66
Ordenar no está en su lugar por defecto! Por lo tanto, debe asignar el resultado del sortmétodo a una variable o agregar inplace=Truea la llamada al método.
Renadeen
2
@renadeen muy buen punto, he actualizado por respuesta con ese comentario.
Andy Hayden
1
¡Me sorprendió saber hoy que ese tipo ha quedado en desuso! Basado en algunas de las opiniones en esta meta publicación: meta.stackoverflow.com/questions/297404/… Decidí agregar una nueva respuesta en lugar de intentar editar la suya
Kyle Heuton
2
@Snoozer Sí, no creo que la clasificación vaya a desaparecer (principalmente porque se usa ampliamente en el libro de Wes), pero ha habido algunos cambios importantes en la clasificación de llamadas . ¡Gracias! ¡Realmente necesito automatizar la revisión de todas mis miles de respuestas de pandas por desaprobación!
Andy Hayden
40

A partir de pandas 0.17.0, DataFrame.sort()está en desuso y está configurado para eliminarse en una versión futura de pandas. La forma de ordenar un marco de datos por sus valores ahora esDataFrame.sort_values

Como tal, la respuesta a su pregunta ahora sería

df.sort_values(['b', 'c'], ascending=[True, False], inplace=True)
Kyle Heuton
fuente
4

Para grandes marcos de datos numéricos, puede ver una mejora significativa en el rendimiento a través de numpy.lexsort, que realiza una ordenación indirecta utilizando una secuencia de teclas:

import pandas as pd
import numpy as np

np.random.seed(0)

df1 = pd.DataFrame(np.random.randint(1, 5, (10,2)), columns=['a','b'])
df1 = pd.concat([df1]*100000)

def pdsort(df1):
    return df1.sort_values(['a', 'b'], ascending=[True, False])

def lex(df1):
    arr = df1.values
    return pd.DataFrame(arr[np.lexsort((-arr[:, 1], arr[:, 0]))])

assert (pdsort(df1).values == lex(df1).values).all()

%timeit pdsort(df1)  # 193 ms per loop
%timeit lex(df1)     # 143 ms per loop

Una peculiaridad es que numpy.lexsortse invierte el orden de clasificación definido : primero se (-'b', 'a')ordena por serie a. Negamos las series bpara reflejar que queremos esta serie en orden descendente.

Tenga en cuenta que np.lexsortsolo se ordena con valores numéricos, mientras que pd.DataFrame.sort_valuesfunciona con cadenas o valores numéricos. El uso np.lexsortcon cuerdas dará: TypeError: bad operand type for unary -: 'str'.

jpp
fuente