Licence CC BY-NC-ND Valérie Roy
_images/ensmp-25-alpha.png

Notebook très rapide !

import pandas as pd
import numpy as np

trier une dataframe

il peut être utile de trier une dataframe selon l’ordre d’une colonne (resp. ligne) de la dataframe et le résultat sera une dataframe dont les lignes (resp. colonnes) auront été réordonnées, les index sont conservés (ils bougent avec les lignes qu’ils indexent …). attention par contre, bien sûr les indices sont modifiés …

c’est l’axe qui indiquera si on trie dans l’axe des lignes (auquel cas on trie selon une colonne) ou si on trie dans l’axe des colonnes (auquel cas on trie selon une ligne).

la fonction est pandas.dataframe.sort_values

Vous pouvez décider de trier en place (inplace=True) auquel cas la dataframe sur laquelle vous appliquez la fonction est modifiée sinon la fonction renverra une dataframe … (si vous voulez une copie, comme toujours précisez le, votre code sera plus clair).

tri d’une dataframe selon une colonne

Reprenons notre exemple du titanic.

file = 'titanic.csv'
df = pd.read_csv(file, index_col=0)
df.head()
Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
PassengerId
1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S

Nous voulons trier la dataframe suivant l’ordre de la colonne de Age. Dans quel axe (axis) devons-nous trier? Vous vous rappelez axis=0 et axis=1?

  • si axis=0 je trie les lignes

  • si axis=1 je trie les colonnes

df_sorted1 = df.sort_values(by='Age', ascending=False, axis=0)
df_sorted1.head(8)
Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
PassengerId
631 1 1 Barkworth, Mr. Algernon Henry Wilson male 80.0 0 0 27042 30.0000 A23 S
852 0 3 Svensson, Mr. Johan male 74.0 0 0 347060 7.7750 NaN S
494 0 1 Artagaveytia, Mr. Ramon male 71.0 0 0 PC 17609 49.5042 NaN C
97 0 1 Goldschmidt, Mr. George B male 71.0 0 0 PC 17754 34.6542 A5 C
117 0 3 Connors, Mr. Patrick male 70.5 0 0 370369 7.7500 NaN Q
673 0 2 Mitchell, Mr. Henry Michael male 70.0 0 0 C.A. 24580 10.5000 NaN S
746 0 1 Crosby, Capt. Edward Gifford male 70.0 1 1 WE/P 5735 71.0000 B22 S
34 0 2 Wheadon, Mr. Edward H male 66.0 0 0 C.A. 24579 10.5000 NaN S

Vous voyez que la colonne des Age est triée, les lignes ont été changées de place dans la table et leur indexation conservée.

Regardons les lignes d’index 673 et 746. Les ages sont identiques, nous aurions pu indiquer une seconde colonne avec by=[col1, col2] pour trier les valeurs trouvées identiques par la première colonne.

Par exemple trions par Age, et si les âges sont égaux, trions par Fare.

df_sorted2 = df.sort_values(by=['Age', 'Fare'], ascending=False, axis=0)
df_sorted2.head(8)
Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
PassengerId
631 1 1 Barkworth, Mr. Algernon Henry Wilson male 80.0 0 0 27042 30.0000 A23 S
852 0 3 Svensson, Mr. Johan male 74.0 0 0 347060 7.7750 NaN S
494 0 1 Artagaveytia, Mr. Ramon male 71.0 0 0 PC 17609 49.5042 NaN C
97 0 1 Goldschmidt, Mr. George B male 71.0 0 0 PC 17754 34.6542 A5 C
117 0 3 Connors, Mr. Patrick male 70.5 0 0 370369 7.7500 NaN Q
746 0 1 Crosby, Capt. Edward Gifford male 70.0 1 1 WE/P 5735 71.0000 B22 S
673 0 2 Mitchell, Mr. Henry Michael male 70.0 0 0 C.A. 24580 10.5000 NaN S
34 0 2 Wheadon, Mr. Edward H male 66.0 0 0 C.A. 24579 10.5000 NaN S

Vous voyez que les lignes d’index 746 et 673, dont les âges sont égaux, ont été triées par Fare et ont changé d’ordre par rapport à la première dataframe df_sorted1.

Si vous voulez modifier la dataframe initiale faites le tri en place en passant le paramètre inplace=True.

Une dernière question: Où sont les lignes dont les valeurs concernées par le tri ne sont pas connues (i.e. np.nan)?

Listons les 5 dernières lignes de la dataframe avec la méthode pandas.DataFrame.tail

df.sort_values(by='Age', ascending=False, axis=0).tail() # oui à la fin
Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
PassengerId
860 0 3 Razi, Mr. Raihed male NaN 0 0 2629 7.2292 NaN C
864 0 3 Sage, Miss. Dorothy Edith "Dolly" female NaN 8 2 CA. 2343 69.5500 NaN S
869 0 3 van Melkebeke, Mr. Philemon male NaN 0 0 345777 9.5000 NaN S
879 0 3 Laleff, Mr. Kristo male NaN 0 0 349217 7.8958 NaN S
889 0 3 Johnston, Miss. Catherine Helen "Carrie" female NaN 1 2 W./C. 6607 23.4500 NaN S

Il est possible de les mettre en début de la dataframe:

df.sort_values(by='Age', ascending=False, axis=0, na_position='first').head()
Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
PassengerId
6 0 3 Moran, Mr. James male NaN 0 0 330877 8.4583 NaN Q
18 1 2 Williams, Mr. Charles Eugene male NaN 0 0 244373 13.0000 NaN S
20 1 3 Masselmani, Mrs. Fatima female NaN 0 0 2649 7.2250 NaN C
27 0 3 Emir, Mr. Farred Chehab male NaN 0 0 2631 7.2250 NaN C
29 1 3 O'Dwyer, Miss. Ellen "Nellie" female NaN 0 0 330959 7.8792 NaN Q

tri d’une dataframe selon une ligne

L’exemple du Titanic se prête mal à cet exemple. Créons une dataframe bidon à partir d’un np.ndarray. Donnons lui un index de colonnes et un de lignes.

petite_df = pd.DataFrame(np.random.randint(-10, 10, 20).reshape(4, 5),
                         columns=['d', 'e', 'a', 'c', 'b'])
petite_df.index = ['un', 'deux', 'trois', 'quatre']
petite_df
d e a c b
un -2 -8 -1 8 -7
deux 7 9 1 5 3
trois -1 6 -1 -3 -5
quatre -1 -6 -4 7 9

Trions la dataframe par la ligne d’index un donc axis=1

petite_df.sort_values(by='un', axis=1)
e b d a c
un -8 -7 -2 -1 8
deux 9 3 7 1 5
trois 6 -5 -1 -1 -3
quatre -6 9 -1 -4 7

Vous voyez que la ligne ‘un’ a été triée et la dataframe réorganisée autour de cette ligne en conservant les index.

tri des index

Comme son nom d’indique, nous allons pouvoir trier les index d’une dataframe, et comme toujours, suivant l’axe 0 pour les lignes, et suivant l’axe 1 pour les colonnes.

Par exemple, nous pouvons trier l’index des colonnes (axis=1) de df.

Regardons la dataframe.

df.head(6)
Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
PassengerId
1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
6 0 3 Moran, Mr. James male NaN 0 0 330877 8.4583 NaN Q

Trions ses noms de colonnes et affichons le header de la dataframe.

df.sort_index(axis=1).head()
Age Cabin Embarked Fare Name Parch Pclass Sex SibSp Survived Ticket
PassengerId
1 22.0 NaN S 7.2500 Braund, Mr. Owen Harris 0 3 male 1 0 A/5 21171
2 38.0 C85 C 71.2833 Cumings, Mrs. John Bradley (Florence Briggs Th... 0 1 female 1 1 PC 17599
3 26.0 NaN S 7.9250 Heikkinen, Miss. Laina 0 3 female 0 1 STON/O2. 3101282
4 35.0 C123 S 53.1000 Futrelle, Mrs. Jacques Heath (Lily May Peel) 0 1 female 1 1 113803
5 35.0 NaN S 8.0500 Allen, Mr. William Henry 0 3 male 0 0 373450

Les colonnes ont bien été réordonnées par ordre lexicographique croissant.

Maintenant, trions l’index des lignes (axis=0) de df_sorted1 (parce que celui de df est déjà trié).

Regardons avant le tri:

df_sorted1.head(6)
Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
PassengerId
631 1 1 Barkworth, Mr. Algernon Henry Wilson male 80.0 0 0 27042 30.0000 A23 S
852 0 3 Svensson, Mr. Johan male 74.0 0 0 347060 7.7750 NaN S
494 0 1 Artagaveytia, Mr. Ramon male 71.0 0 0 PC 17609 49.5042 NaN C
97 0 1 Goldschmidt, Mr. George B male 71.0 0 0 PC 17754 34.6542 A5 C
117 0 3 Connors, Mr. Patrick male 70.5 0 0 370369 7.7500 NaN Q
673 0 2 Mitchell, Mr. Henry Michael male 70.0 0 0 C.A. 24580 10.5000 NaN S

Trions et regardons après le tri.

df_sorted1.sort_index(axis=0).head()
Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
PassengerId
1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S

Voilà l’index PassengerId tout bien réordonné !