sort() ordina i valori di un vettore
Per un semplice vettore, sort() fa esattamente quello che ti aspetti: restituisce i valori in ordine crescente (l'originale resta intatto):
Due opzioni da conoscere. decreasing = TRUE inverte la direzione. E di default sort() scarta in silenzio i valori NA: sort(c(3, NA, 1)) restituisce solo 1 3. Se i valori mancanti devono sopravvivere all'ordinamento, di' dove metterli: sort(x, na.last = TRUE) li conserva, dopo i valori ordinati.
Fin qui, tutto ovvio. La parte interessante è capire perché sort() è lo strumento sbagliato per i data frame.
order() restituisce posizioni: il cambio di prospettiva
sort() risponde a "quali sono i valori, in ordine?". order() risponde a una domanda diversa: "quali posizioni dovrei visitare per vedere i valori in ordine?"
Leggi order(times) come un'istruzione: il valore più piccolo sta in posizione 2, il successivo in posizione 4, poi 1, poi 3. Indicizzando con queste istruzioni, times[order(times)], riproduci esattamente sort(times).
Perché è importante? Perché una riga di un data frame è una squadra di valori che devono muoversi insieme. Ordinare da sola la colonna time con sort() riordinerebbe una colonna lasciando indietro le compagne: ogni riga mescolata. order() invece ti dà le posizioni delle righe, e mettendo le posizioni nello spazio delle righe tra le parentesi quadre sposti righe intere:
Il 9.8 di Ben arriva con il nome di Ben ancora attaccato. È tutto qui il trucco, ed è *l'*idioma per ordinare i data frame in R base: df[order(df$column), ]. (Le etichette di riga stampate, 2 4 1 3, sono i numeri di riga originali che si portano dietro; innocue.)
Ordine decrescente e su più colonne
Per un ordinamento numerico decrescente, nega la colonna: ordinare -time in modo crescente equivale a ordinare time in modo decrescente. E order() accetta più colonne, prima le prime e poi le successive per risolvere i pareggi:
La seconda chiamata ordina i reparti in ordine alfabetico e, dentro ogni reparto, gli stipendi dal più alto al più basso. Il trucco della negazione funziona solo con i numeri: -df$name su una colonna di caratteri è un errore. Per il testo in ordine decrescente usa invece order(df$name, decreasing = TRUE) (che inverte tutte le chiavi di ordinamento insieme).
rank() è il terzo fratello
Di passaggio: rank(x) risponde a un'altra domanda ancora, "che posto occupa ogni valore?", senza spostare niente:
sort() dà i valori ordinati, order() dà le posizioni da visitare, rank() dà la posizione in classifica di ogni valore, lasciandolo dov'è. Si confondono continuamente order() e rank(); nota che sono permutazioni inverse l'una dell'altra, e usa rank() solo quando vuoi davvero delle posizioni in classifica (classifiche, percentili).
Il modo dplyr: arrange()
arrange() di dplyr racchiude tutta la danza di order() in un verbo: le colonne sono le chiavi di ordinamento e desc() ne inverte una (codice statico: la sandbox esegue solo R base):
library(dplyr)
runners |> arrange(time)
staff |> arrange(dept, desc(salary))
Niente parentesi quadre, niente $, niente trucco della negazione: desc() funziona anche sulle colonne di caratteri. Una differenza di comportamento da conoscere: arrange() mette i valori NA in fondo qualunque sia la direzione, mentre order() di base usa anch'esso na.last = TRUE come default. Vedi l'introduzione a dplyr per come arrange() si concatena con filter() e compagnia.
L'ordinamento dei caratteri ha i suoi spigoli
Due avvertenze quando ordini del testo. Primo, le cifre salvate come testo si ordinano come testo: il confronto tra caratteri procede simbolo per simbolo:
"10" viene prima di "2" perché il confronto si ferma al primo simbolo: "1" < "2". Se una colonna di numeri si ordina in modo strano, quasi sicuramente è salvata come carattere: convertila prima con as.numeric() (una conseguenza frequente di un'importazione CSV disordinata).
Secondo, l'ordine del testo dipende dal locale del sistema: accenti, maiuscole e alfabeti non latini possono ordinarsi in modo diverso sul tuo portatile rispetto a un server con locale C. Un output ordinato che deve essere identico su macchine diverse dovrebbe impostare il locale in modo esplicito oppure ordinare una chiave normalizzata.
Cosa ti porti a casa
sort(x)ordina i valori di un vettore;decreasing = TRUEinverte l'ordine; gliNAvengono scartati a meno dina.last = TRUE.order(x)restituisce posizioni, edf[order(df$x), ]è *l'*idioma di base per ordinare i data frame.- Su più colonne:
order(df$a, -df$b); la negazione per l'ordine decrescente funziona solo con i numeri. rank()dà le posizioni in classifica senza riordinare: non sostituisceorder().arrange(dept, desc(salary))di dplyr è lo stesso ordinamento con meno punteggiatura.- Nel testo
"10"viene prima di"2": controlla i tipi delle tue colonne.
Prossimo passo: riassumere le righe per gruppi con table(), tapply(), aggregate() e group_by() di dplyr.
Domande frequenti
Come si ordina un data frame per una colonna in R?
Usa order() dentro le parentesi quadre delle righe: df[order(df$price), ]. order() restituisce le posizioni delle righe nell'ordine giusto, e indicizzando con esse riorganizzi l'intero data frame. sort() qui non funziona: ordina i valori di un solo vettore, perdendo il loro legame con le altre colonne.
Qual è la differenza tra sort() e order() in R?
sort(x) restituisce i valori di x riordinati. order(x) restituisce le posizioni (gli indici) che metterebbero x in ordine, ed è ciò che ti serve per ordinare un intero data frame in base a una sua colonna: df[order(df$x), ].
Come si ordina in modo decrescente in R?
Per un vettore: sort(x, decreasing = TRUE). Per un data frame: df[order(-df$x), ] (neghi una colonna numerica) oppure df[order(df$x, decreasing = TRUE), ], che funziona anche con le colonne di caratteri, dove la negazione non si può usare. In dplyr: arrange(df, desc(x)).
Come si ordina per più colonne in R?
Passale tutte a order(): df[order(df$dept, -df$salary), ] ordina per reparto e poi, dentro ogni reparto, per stipendio decrescente. I primi argomenti sono le chiavi principali; quelli successivi risolvono i pareggi. In dplyr: arrange(df, dept, desc(salary)).