Ordenar barras en ggplot2 gráfico de barras

Intento hacer un gráfico de barras donde la barra más grande estaría más cerca del eje y y la barra más corta sería la más alejada. Entonces esto es como la Tabla I

Name Position 1 James Goalkeeper 2 Frank Goalkeeper 3 Jean Defense 4 Steve Defense 5 John Defense 6 Tim Striker 

Así que estoy tratando de construir un gráfico de barras que muestre el número de jugadores según la posición

 p <- ggplot(theTable, aes(x = Position)) + geom_bar(binwidth = 1) 

pero el gráfico muestra primero la barra del portero y luego la defensa, y finalmente el delantero. Me gustaría ordenar el gráfico para que la barra de defensa esté más cerca del eje y, el portero uno, y finalmente el delantero uno. Gracias

La clave con el pedido es establecer los niveles del factor en el orden que desee. No se requiere un factor ordenado; la información adicional en un factor ordenado no es necesaria y si estos datos se están utilizando en cualquier modelo estadístico, podría producirse una parametrización incorrecta; los contrastes polinomiales no son adecuados para datos nominales como este.

 ## set the levels in order we want theTable <- within(theTable, Position <- factor(Position, levels=names(sort(table(Position), decreasing=TRUE)))) ## plot ggplot(theTable,aes(x=Position))+geom_bar(binwidth=1) 

figura de barra

En el sentido más general, simplemente necesitamos establecer los niveles de los factores para que estén en el orden deseado. Si no se especifica, los niveles de un factor se ordenarán alfabéticamente. Sin embargo, existen múltiples formas de cambiar el orden a una secuencia específica según la situación. Por ejemplo, podríamos hacer:

 levels(theTable$Position) <- c(...) 

y simplemente liste los niveles en el orden deseado en el lado derecho. También puede especificar el orden de nivel dentro de la llamada para factorizar como arriba:

 theTable$Position <- factor(theTable$Position, levels = c(...)) 

@GavinSimpson: reorder es una solución poderosa y efectiva para esto:

 ggplot(theTable, aes(x=reorder(Position,Position, function(x)-length(x)))) + geom_bar() 

Usando scale_x_discrete (limits = ...) para especificar el orden de las barras.

 positions <- c("Goalkeeper", "Defense", "Striker") p <- ggplot(theTable, aes(x = Position)) + scale_x_discrete(limits = positions) 

Creo que las soluciones ya proporcionadas son excesivamente detalladas. Una forma más concisa de hacer una barra de barras ordenada por frecuencia con ggplot es

 ggplot(theTable, aes(x=reorder(Position, -table(Position)[Position]))) + geom_bar() 

Es similar a lo que sugirió Alex Brown, pero es un poco más corto y funciona sin una definición de función anynymous.

Actualizar

Creo que mi solución anterior era buena en ese momento, pero hoy en día prefiero usar forcats::fct_infreq que es ordenar los niveles de factor por frecuencia:

 require(forcats) ggplot(theTable, aes(fct_infreq(Position))) + geom_bar() 

Solo necesita especificar que la columna Position sea ​​un factor ordenado donde los niveles están ordenados por sus recuentos:

 theTable <- transform( theTable, Position = ordered(Position, levels = names( sort(-table(Position))))) 

(Tenga en cuenta que la table(Position) produce un recuento de frecuencia de la columna Position ).

Luego su función ggplot mostrará las barras en orden decreciente de conteo. No sé si hay una opción en geom_bar para hacer esto sin tener que crear explícitamente un factor ordenado.

Al igual que reorder() en la respuesta de Alex Brown, también podríamos usar forcats::fct_reorder() . Básicamente, clasificará los factores especificados en el 1er arg, de acuerdo con los valores del 2º arg después de aplicar una función específica (por defecto = mediana, que es lo que usamos aquí ya que solo tenemos un valor por nivel de factor).

Es una pena que en la pregunta del OP, el orden requerido también sea alfabético ya que ese es el orden de clasificación predeterminado cuando se crean factores, por lo que se ocultará lo que está haciendo realmente esta función. Para hacerlo más claro, reemplazaré “Portero” con “Zoalkeeper”.

 library(tidyverse) library(forcats) theTable <- data.frame( Name = c('James', 'Frank', 'Jean', 'Steve', 'John', 'Tim'), Position = c('Zoalkeeper', 'Zoalkeeper', 'Defense', 'Defense', 'Defense', 'Striker')) theTable %>% count(Position) %>% mutate(Position = fct_reorder(Position, n, .desc = TRUE)) %>% ggplot(aes(x = Position, y = n)) + geom_bar(stat = 'identity') 

enter image description here

Un simple reordenamiento de factores basado en dplyr puede resolver este problema:

 library(dplyr) #reorder the table and reset the factor to that ordering theTable %>% group_by(Position) %>% # calculate the counts summarize(counts = n()) %>% arrange(-counts) %>% # sort by counts mutate(Position = factor(Position, Position)) %>% # reset factor ggplot(aes(x=Position, y=counts)) + # plot geom_bar(stat="identity") # plot histogram 

Estoy de acuerdo con Zach en que contar dentro de Dplyr es la mejor solución. He encontrado que esta es la versión más corta:

 dplyr::count(theTable, Position) %>% arrange(-n) %>% mutate(Position = factor(Position, Position)) %>% ggplot(aes(x=Position, y=n)) + geom_bar(stat="identity") 

Esto también será significativamente más rápido que reordenar los niveles de factores de antemano ya que el recuento se realiza en dplyr no en ggplot o usando la table .

Además de forcats :: fct_infreq, mencionado por @HolgerBrandl, hay forcats :: fct_rev, que revierte el orden de los factores.

 theTable <- data.frame( Position= c("Zoalkeeper", "Zoalkeeper", "Defense", "Defense", "Defense", "Striker"), Name=c("James", "Frank","Jean", "Steve","John", "Tim")) p1 <- ggplot(theTable, aes(x = Position)) + geom_bar() p2 <- ggplot(theTable, aes(x = fct_infreq(Position))) + geom_bar() p3 <- ggplot(theTable, aes(x = fct_rev(fct_infreq(Position)))) + geom_bar() gridExtra::grid.arrange(p1, p2, p3, nrow=3) 

gplot de salida

Si las columnas del gráfico provienen de una variable numérica como en el dataframe a continuación, puede usar una solución más simple:

 ggplot(df, aes(x = reorder(Colors, -Qty, sum), y = Qty)) + geom_bar(stat = "identity") 

El signo menos antes de la variable de ordenación (-Qty) controla la dirección de clasificación (ascendente / descendente)

Aquí hay algunos datos para probar:

 df <- data.frame(Colors = c("Green","Yellow","Blue","Red","Yellow","Blue"), Qty = c(7,4,5,1,3,6) ) **Sample data:** Colors Qty 1 Green 7 2 Yellow 4 3 Blue 5 4 Red 1 5 Yellow 3 6 Blue 6 

Cuando encontré este hilo, esa fue la respuesta que estaba buscando. Espero que sea útil para otros.