sort() trie les valeurs d'un vecteur
Pour un vecteur simple, sort() fait exactement ce que tu attends - il renvoie les valeurs en ordre croissant (l'original n'est pas touché) :
Deux options à connaître. decreasing = TRUE inverse le sens. Et sort() écarte silencieusement les valeurs NA par défaut - sort(c(3, NA, 1)) renvoie juste 1 3. Si les valeurs manquantes doivent survivre au tri, dis où elles vont : sort(x, na.last = TRUE) les garde, placées après les valeurs ordonnées.
Jusqu'ici, rien d'étonnant. L'intéressant, c'est pourquoi sort() est le mauvais outil pour les data frames.
order() renvoie des positions - le déclic mental
sort() répond à « quelles sont les valeurs, dans l'ordre ? ». order() répond à une autre question : « quelles positions dois-je visiter pour voir les valeurs dans l'ordre ? »
Lis order(times) comme des instructions : la plus petite valeur est en position 2, la suivante en position 4, puis 1, puis 3. Indexer avec ces instructions - times[order(times)] - reproduit exactement sort(times).
Pourquoi est-ce important ? Parce qu'une ligne de data frame est une équipe de valeurs qui doivent bouger ensemble. Trier la seule colonne time avec sort() réordonnerait une colonne en laissant ses coéquipières sur place - toutes les lignes mélangées. order() te donne des positions de lignes à la place, et mettre ces positions dans l'emplacement des lignes des crochets déplace des lignes entières :
Le 9.8 de Ben arrive avec le nom de Ben toujours attaché. Voilà toute l'astuce, et c'est *l'*idiome pour trier des data frames en R de base : df[order(df$colonne), ]. (Les étiquettes de lignes affichées - 2 4 1 3 - sont les numéros de lignes d'origine qui suivent ; inoffensif.)
Tris décroissants et multi-colonnes
Pour un tri numérique décroissant, nie la colonne - ordonner -time en croissant revient à ordonner time en décroissant. Et order() accepte plusieurs colonnes, les premières d'abord, les suivantes départageant les égalités :
Le second appel trie les services par ordre alphabétique et, à l'intérieur de chaque service, les salaires du plus haut au plus bas. L'astuce de la négation ne marche que sur des nombres - -df$name sur une colonne texte est une erreur. Pour du texte décroissant, utilise plutôt order(df$name, decreasing = TRUE) (qui inverse toutes les clés de tri à la fois).
rank() est le troisième frère
Au passage : rank(x) répond à encore une autre question - « quelle place occupe chaque valeur ? » - sans rien déplacer :
sort() donne les valeurs ordonnées, order() donne les positions à visiter, rank() donne le classement de chaque valeur sur place. Les gens confondent constamment order() et rank() ; note que ce sont des permutations inverses l'une de l'autre, et ne sors rank() que quand tu veux littéralement des classements (tableaux de scores, percentiles).
La façon dplyr : arrange()
arrange() de dplyr enveloppe toute la danse d'order() dans un verbe - les colonnes sont des clés de tri, desc() en inverse une (statique ; le bac à sable n'exécute que du R de base) :
library(dplyr)
runners |> arrange(time)
staff |> arrange(dept, desc(salary))
Pas de crochets, pas de $, pas d'astuce de négation - desc() marche aussi sur les colonnes texte. Une différence de comportement à connaître : arrange() place les valeurs NA à la fin quelle que soit la direction, tandis que le order() de base utilise aussi na.last = TRUE par défaut. Voir l'intro à dplyr pour la façon dont arrange() s'enchaîne avec filter() et compagnie.
Le tri de texte a des angles vifs
Deux mises en garde quand tu tries du texte. D'abord, des chiffres stockés en texte se trient comme du texte - la comparaison de caractères se fait symbole par symbole :
"10" se trie avant "2" parce que la comparaison s'arrête au premier symbole : "1" < "2". Si une colonne de nombres se trie bizarrement, elle est presque certainement stockée en character - convertis d'abord avec as.numeric() (une conséquence fréquente d'un import CSV brouillon).
Ensuite, l'ordre du texte dépend de la locale de ton système - accents, casse et écritures non latines peuvent se trier différemment sur ton portable et sur un serveur en locale C. Une sortie triée qui doit être identique d'une machine à l'autre devrait soit fixer explicitement la locale, soit trier sur une clé normalisée.
Ce que tu retiens
sort(x)ordonne les valeurs d'un vecteur ;decreasing = TRUEinverse ; lesNAsont écartés sauf avecna.last = TRUE.order(x)renvoie des positions, etdf[order(df$x), ]est *l'*idiome de base pour trier des data frames.- Multi-colonnes :
order(df$a, -df$b); la négation pour le décroissant ne marche que sur les nombres. rank()donne des classements sans réordonner - ce n'est pas un substitut d'order().arrange(dept, desc(salary))de dplyr fait le même tri avec moins de ponctuation."10"se trie avant"2"en texte - vérifie les types de tes colonnes.
Prochaine étape : réduire des lignes en résumés par groupe avec table(), tapply(), aggregate() et le group_by() de dplyr.
Questions fréquentes
Comment trier un data frame par une colonne en R ?
Utilise order() dans les crochets de lignes : df[order(df$price), ]. order() renvoie les positions des lignes dans l'ordre trié, et indexer avec elles réorganise tout le data frame. sort() ne marchera pas ici - il trie les valeurs d'un seul vecteur, en perdant leur lien avec les autres colonnes.
Quelle est la différence entre sort() et order() en R ?
sort(x) renvoie les valeurs de x réarrangées dans l'ordre. order(x) renvoie les positions (indices) qui mettraient x dans l'ordre - ce dont tu as besoin pour trier tout un data frame selon l'une de ses colonnes : df[order(df$x), ].
Comment trier par ordre décroissant en R ?
Pour un vecteur : sort(x, decreasing = TRUE). Pour un data frame : df[order(-df$x), ] (nier une colonne numérique) ou df[order(df$x, decreasing = TRUE), ], qui marche aussi pour les colonnes texte où la négation est impossible. En dplyr : arrange(df, desc(x)).
Comment trier par plusieurs colonnes en R ?
Passe-les toutes à order() : df[order(df$dept, -df$salary), ] trie par service, puis par salaire décroissant dans chaque service. Les premiers arguments sont les clés principales ; les suivants départagent les égalités. En dplyr : arrange(df, dept, desc(salary)).