Cambia el orden de una escala x discreta

Estoy haciendo un gráfico de barras esquivado usando ggplot con escala x discreta, los ejes x ahora están ordenados alfabéticamente, pero necesito reorganizarlo para que esté ordenado por el valor del eje y (es decir, la barra más alta posicionarse a la izquierda).

Intenté ordenar u ordenar, pero el resultado es ordenar el eje x, pero no las barras, respectivamente.

¿Qué he hecho mal?

Intente configurar manualmente los niveles del factor en el eje x. Por ejemplo:

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

ggplot del conjunto de datos de los automóviles con niveles de factores determinados automáticamente

 # 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 conjunto de datos de automóviles con niveles de factor reordenados manualmente

Como James señaló en su respuesta, reorder es la manera idiomática de reordenar los niveles de los factores.

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

ggplot del conjunto de datos de automóviles con niveles de factores reordenados utilizando la función de reordenar

La mejor manera para mí fue usar vector con categorías para poder usar el parámetro de limits a scale_x_discrete . Creo que es una solución bastante simple y directa.

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

enter image description here

Puedes usar reorder :

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

Editar:

Para tener la barra más alta a la izquierda, debes usar un poco de kludge:

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

Yo esperaría que esto también tenga alturas negativas, pero no funciona, ¡así que funciona!

Hadley ha estado desarrollando un paquete llamado forcats . Este paquete hace que la tarea sea mucho más fácil. Puede explotar fct_infreq() cuando desee cambiar el orden del eje x por la frecuencia de un factor. En el caso del ejemplo de mtcars en esta publicación, desea reordenar los niveles de cyl por la frecuencia de cada nivel. El nivel que aparece con mayor frecuencia permanece en el lado izquierdo. Todo lo que necesitas es fct_infreq() .

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

Si quieres ir al revés, puedes usar fct_rev() junto con fct_infreq() .

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

enter image description here

Me doy cuenta de que esto es antiguo, pero tal vez esta función que he creado es útil para alguien que está afuera:

 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))) } 

Ahora, con esta función puedes trazar de forma interactiva con ggplot2, así:

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

Como se puede ver, la función order_axis crea otro dataframe con una nueva columna llamada igual pero con un _o al final. Esta nueva columna tiene niveles en orden ascendente, por lo que ggplot2 traza automáticamente en ese orden.

Esto es algo limitado (solo funciona para caracteres o factores y combinaciones numéricas de columnas y en orden ascendente) pero todavía lo encuentro muy útil para trazar sobre la marcha.