2010-07-15 6 views
84

Sto creando un grafico a barre con ggplot con scala x discreta, l'asse x ora è disposto in ordine alfabetico, ma ho bisogno di riorganizzarlo in modo che sia ordinato in base al valore di l'asse y (cioè, la barra più alta sarà posizionata a sinistra).Modificare l'ordine di una scala x discreta

Ho provato l'ordine o l'ordinamento, ma il risultato è di ordinare l'asse x, ma non le barre rispettivamente.

Cosa ho fatto di sbagliato?

risposta

77

Provare manualmente ad impostare i livelli del fattore sull'asse x. Per esempio:

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

ggplot of the cars dataset with factor levels automatically determined

# 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 of the cars dataset with factor levels reordered manually

Come James ha sottolineato nella sua risposta, reorder è il modo idiomatico di riordino livelli di fattore.

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

ggplot of the cars dataset with factor levels reordered using the reorder function

25

È possibile utilizzare reorder:

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

Edit:

Per avere la barra più alto a sinistra, è necessario utilizzare un po 'di un kludge :

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

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

+5

Sono scioccato questa risposta non ha più upvotes, il 90% del tempo questo è il modo corretto di farlo. – Gregor

+0

Penso che sia il richiamo dei fattori sia superfluo. Esiste un richiamo implicito al fattore per il primo argomento e si suppone che il secondo argomento sia numerico. –

134

Il modo migliore per me era utilizzare il vettore con le categorie in modo da avere bisogno come parametro limits su scale_x_discrete. Penso che sia una soluzione piuttosto semplice e diretta.

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

enter image description here

+1

Questo "funziona" .... ma la legenda mostra ancora gli ordini confusi ... –

+0

@HendyIrawan non c'è nessuna leggenda se non hai altre dimensioni (colore, riempimento) anche associate alla stessa variabile. – Gregor

2

Mi rendo conto che è vecchio, ma forse questa funzione 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, così:

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

Come si può vedere, loLa funzionecrea un altro dataframe con una nuova colonna denominata uguale ma con un _o alla fine. Questa nuova colonna ha livelli in ordine crescente, quindi ggplot2 traccia automaticamente in tale ordine.

Questo è un po 'limitato (funziona solo per caratteri o combinazioni di fattori e numerici di colonne e in ordine ascendente) ma lo trovo ancora molto utile per il tracciamento in movimento.

13

Hadley ha sviluppato un pacchetto chiamato forcats. Questo pacchetto rende l'attività molto più semplice.È possibile sfruttare fct_infreq() quando si desidera modificare l'ordine dell'asse x in base alla frequenza di un fattore. Nel caso dell'esempio mtcars in questo post, si desidera riordinare i livelli di cyl in base alla frequenza di ciascun livello. Il livello che appare più frequentemente rimane sul lato sinistro. Tutto ciò di cui hai bisogno è lo fct_infreq().

library(ggplot2) 
library(forcats) 

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

Se si vuole andare il contrario, è possibile utilizzare fct_rev() con fct_infreq().

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

enter image description here

Problemi correlati