web-dev-qa-db-fra.com

Comment trier un dataFrame dans python pandas par deux colonnes ou plus?

Supposons que j'ai un cadre de données avec des colonnes a, b et c, je veux trier le cadre de données par colonne b dans l'ordre croissant, et par colonne c par ordre décroissant, comment faire cela?

189
Rakesh Adhikesavan

À partir de la version 0.17.0, la méthode sort était obsolète en faveur de sort_values . sort a été complètement supprimé de la version 0.20.0. Les arguments (et les résultats) restent les mêmes:

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

Vous pouvez utiliser l'argument croissant de sort :

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

Par exemple:

_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
_

Commenté par @renadeen

Le tri n'est pas en place par défaut! Vous devez donc affecter le résultat de la méthode de tri à une variable ou ajouter inplace = True à un appel de méthode.

autrement dit, si vous souhaitez réutiliser df1 en tant que DataFrame trié:

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

ou

_df1.sort(['a', 'b'], ascending=[True, False], inplace=True)
_
342
Andy Hayden

À partir de pandas 0.17.0, DataFrame.sort() est obsolète et doit être supprimé dans une version ultérieure de pandas. Le moyen de trier un cadre de données en fonction de ses valeurs est désormais DataFrame.sort_values

En tant que tel, la réponse à votre question serait maintenant

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

Pour les grandes trames de données numériques, vous pouvez constater une amélioration significative des performances via numpy.lexsort , qui effectue un tri indirect à l'aide d'une séquence de clés:

_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
_

Une particularité est que l'ordre de tri défini avec _numpy.lexsort_ est inversé: _(-'b', 'a')_ trie par série a en premier. Nous nions la série b pour refléter le fait que nous voulons cette série par ordre décroissant.

1
jpp