Ordina una scala x discreta per frequenza / valore


137

Sto creando un grafico a barre schivato usando ggplot con scala x discreta, l'asse x ora è organizzato in ordine alfabetico, ma ho bisogno di riorganizzarlo in modo che sia ordinato dal valore dell'asse y (cioè, la barra più alta sarà essere posizionato a sinistra).

Ho provato a ordinare o ordinare, ma ho come risultato l'ordinamento dell'asse x, ma non delle barre rispettivamente.

Cosa ho fatto di sbagliato?

Risposte:


105

Prova a impostare manualmente i livelli del fattore sull'asse x. Per esempio:

library(ggplot2)
# Automatic levels
ggplot(mtcars, aes(factor(cyl))) + geom_bar()    

ggplot del set di dati delle auto con livelli di fattore determinati automaticamente

# Manual levels
cyl_table <- table(mtcars$cyl)
cyl_levels <- names(cyl_table)[order(cyl_table)]
mtcars$cyl2 <- factor(mtcars$cyl, levels = cyl_levels)
# Just to be clear, the above line is no different than:
# mtcars$cyl2 <- factor(mtcars$cyl, levels = c("6","4","8"))
# You can manually set the levels in whatever order you please. 
ggplot(mtcars, aes(cyl2)) + geom_bar()

ggplot del set di dati delle auto con livelli di fattore riordinati manualmente

Come James ha sottolineato nella sua risposta, reorderè il modo idiomatico di riordinare i livelli dei fattori.

mtcars$cyl3 <- with(mtcars, reorder(cyl, cyl, function(x) -length(x)))
ggplot(mtcars, aes(cyl3)) + geom_bar()

ggplot del set di dati delle auto con livelli di fattore riordinati utilizzando la funzione di riordino


197

Il modo migliore per me era usare il vettore con le categorie per cui ho bisogno come limitsparametro scale_x_discrete. Penso che sia una soluzione abbastanza semplice e diretta.

ggplot(mtcars, aes(factor(cyl))) + 
  geom_bar() + 
  scale_x_discrete(limits=c(8,4,6))

inserisci qui la descrizione dell'immagine


1
@HendyIrawan non esiste una legenda a meno che tu non abbia anche altre dimensioni (colore, riempimento) mappate sulla stessa variabile.
Gregor Thomas,

5
Penso che questa sia la risposta migliore. Controlla l'ordine dei valori dell'asse x e non trasforma né influenza il frame di dati. L'uso factore la reordermodifica delle caratteristiche dei dati, sebbene all'interno della ggplot()chiamata, e così fa più di quanto sia necessario per il problema in questione.
mjandrews,

2
Questa dovrebbe essere la risposta accettata !! Perché complicare le cose scrivendo da 2 a 3 righe di codice per qualcosa che puoi fare in una singola elegante (predefinita) riga di codice?
SilSur,

1
Questo ha funzionato anche per me per ordinare x in base al valore di y: scale_x_discrete(limits = DT$x[order(-DT$y)])+
armipunk

38

Puoi usare reorder:

qplot(reorder(factor(cyl),factor(cyl),length),data=mtcars,geom="bar")

Modificare:

Per avere la barra più alta a sinistra, devi usare un po 'di kludge:

qplot(reorder(factor(cyl),factor(cyl),function(x) length(x)*-1),
   data=mtcars,geom="bar")

Mi aspetto che anche questo abbia altezze negative, ma non funziona, quindi funziona!


5
Sono scioccato che questa risposta non abbia più voti, il 90% delle volte questo è il modo corretto di farlo.
Gregor Thomas,

1
Penso che entrambe le chiamate ai fattori siano superflue. Esiste una chiamata implicita al fattore per il primo argomento e si ritiene che il secondo argomento sia numerico.
IRTFM,

Una spiegazione che mi ha aiutato a capire cosa stavano facendo queste soluzioni sotto il cofano: rstudio-pubs-static.s3.amazonaws.com/…
keithpjolley

30

Hadley ha sviluppato un pacchetto chiamato forcats. Questo pacchetto semplifica notevolmente l'attività. Puoi sfruttare fct_infreq()quando vuoi cambiare l'ordine dell'asse x dalla frequenza di un fattore. Nel caso mtcarsdell'esempio in questo post, si desidera riordinare i livelli in cylbase alla frequenza di ciascun livello. Il livello che appare più frequentemente rimane sul lato sinistro. Tutto ciò che serve è il fct_infreq().

library(ggplot2)
library(forcats)

ggplot(mtcars, aes(fct_infreq(factor(cyl)))) +
geom_bar() +
labs(x = "cyl")

Se vuoi fare il contrario, puoi usarlo fct_rev()insieme a fct_infreq().

ggplot(mtcars, aes(fct_rev(fct_infreq(factor(cyl))))) +
geom_bar() +
labs(x = "cyl") 

inserisci qui la descrizione dell'immagine


2

Mi rendo conto che questo è vecchio, ma forse questa funzione che ho creato è utile a qualcuno là fuori:

order_axis<-function(data, axis, column)
{
  # for interactivity with ggplot2
  arguments <- as.list(match.call())
  col <- eval(arguments$column, data)
  ax <- eval(arguments$axis, data)

  # evaluated factors
  a<-reorder(with(data, ax), 
             with(data, col))

  #new_data
  df<-cbind.data.frame(data)
  # define new var
  within(df, 
         do.call("<-",list(paste0(as.character(arguments$axis),"_o"), a)))
}

Ora, con questa funzione è possibile tracciare in modo interattivo con ggplot2, in questo modo:

ggplot(order_axis(df, AXIS_X, COLUMN_Y), 
       aes(x = AXIS_X_o, y = COLUMN_Y)) +
        geom_bar(stat = "identity")

Come si può vedere, la order_axisfunzione crea un altro frame di dati con una nuova colonna denominata uguale ma con un _oalla fine. Questa nuova colonna ha livelli in ordine crescente, quindi ggplot2 traccia automaticamente in quell'ordine.

Questo è un po 'limitato (funziona solo con caratteri o fattori e combinazioni numeriche di colonne e in ordine crescente) ma lo trovo ancora molto utile per la stampa in movimento.


Immagino di non vedere il vantaggio di questo rispetto al solo utilizzo reorderdiretto. Non ggplot(df, aes(x = reorder(AXIS_X, COLUMN_Y), y = COLUMN_Y)) + ...fa la stessa cosa in modo conciso e senza la funzione di aiuto?
Gregor Thomas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.