Ordenar barras en el gráfico de barras ggplot2
Estoy tratando de hacer un gráfico de barras donde la barra más grande sería más cercana al eje y y la barra más corta sería más lejos. Así que esto es como la Tabla que tengo
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 de acuerdo con la posición
p <- ggplot(theTable, aes(x = Position)) + geom_bar(binwidth = 1)
Pero el gráfico muestra la barra de portero primero, luego la defensa, y finalmente el delantero. Me gustaría que el gráfico para ser ordenado de modo que la barra de defensa es más cercano al eje y, el portero uno, y finalmente el delantero uno. Gracias
10 answers
La clave con el orden 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, la parametrización incorrecta podría resultar - los contrastes polinómicos 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)
En el sentido más general, simplemente necesitamos establecer los niveles de factores para que estén en el orden deseado. Si se deja sin especificar, los niveles de un factor se ordenarán alfabéticamente. Sin embargo, hay varias maneras de cambiar el orden a una secuencia específica dependiendo de la situación. Por ejemplo, podríamos hacer:
levels(theTable$Position) <- c(...)
Y simplemente enumere los niveles en el orden deseado en el lado derecho. También puede especificar el orden de nivel dentro de la llamada a factor como se indica arriba:
theTable$Position <- factor(theTable$Position, levels = c(...))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-27 18:48:48
@ GavinSimpson: reorder
es una solución poderosa y efectiva para esto:
ggplot(theTable,
aes(x=reorder(Position,Position,
function(x)-length(x)))) +
geom_bar()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-05 19:50:11
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-02 16:35:27
Creo que las soluciones ya proporcionadas son demasiado detalladas. Una forma más concisa de hacer una gráfica 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 un poco más corto y funciona sin una definición de función anynymous.
Update
Creo que mi antigua solución 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()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-11 14:58:56
Solo necesita especificar la columna Position
para ser 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 el table(Position)
produce un recuento de frecuencias de la columna Position
.)
Entonces su función ggplot
mostrará las barras en orden decreciente de conteo.
No se si hay una opción en geom_bar
para hacer esto sin tener que crear explícitamente un factor ordenado.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-06 14:53:46
Como reorder()
en la respuesta de Alex Brown, también podríamos usar forcats::fct_reorder()
. Básicamente ordenará los factores especificados en el 1er arg, de acuerdo con los valores en el 2do arg después de aplicar una función especificada (default = median, 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 es el orden de clasificación predeterminado cuando crea factores, por lo que ocultará lo que esta función está haciendo realmente. A que quede más claro, voy a 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')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-08 13:35:47
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-04 14:32:17
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 factor de antemano, ya que el recuento se realiza en dplyr no en ggplot o utilizando table
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-04 16:29:43
Además De forcats::fct_infreq, mencionado por @HolgerBrandl, está forcats:: fct_rev, que invierte 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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-25 20:19:04
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 ordenació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 era la respuesta que estaba buscando. Espero que sea útil para otros.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-03 07:17:19