varias superponer los graficos grafico graficas graficar ggplot escala ejes diagrama como cambiar barras avanzados r ggplot2 geom-bar

los - superponer graficas en r ggplot



Diagrama de barra de ggplot con orden de categorías dependiente de facetas (4)

Esta es una pregunta antigua, pero está siendo utilizada como un objetivo para engañar. Por lo tanto, podría valer la pena sugerir una solución que utilice las mejoras recientes del paquete ggplot2 , a saber, el parámetro de labels para scale_x_discrete() . Esto evita usar niveles duplicados que están en desuso o manipular las etiquetas de factores al anteponer un número variable de espacios .

Preparar datos

Aquí, el conjunto de datos mpg se usa para hacer una comparación con esta respuesta . Para la manipulación de datos, el paquete data.table se usa aquí, pero puede usar el paquete que prefiera para este propósito.

library(data.table) # version 1.10.4 library(ggplot2) # version 2.2.1 # aggregate data df <- as.data.table(mpg)[, .(mixmpg = mean(cty + hwy)), by = .(year, manufacturer)] # create dummy var which reflects order when sorted alphabetically df[, ord := sprintf("%02i", frank(df, mixmpg, ties.method = "first"))]

Crear trama

# `ord` is plotted on x-axis instead of `manufacturer` ggplot(df, aes(x = ord, y = mixmpg)) + # geom_col() is replacement for geom_bar(stat = "identity") geom_col() + # independent x-axis scale in each facet, # drop absent factor levels (actually not required here) facet_wrap(~ year, scales = "free_x", drop = TRUE) + # use named character vector to replace x-axis labels scale_x_discrete(labels = df[, setNames(as.character(manufacturer), ord)]) + # replace x-axis title xlab(NULL) + # rotate x-axis labels theme(axis.text.x = element_text(angle = 90, hjust=1, vjust=.5))

He visto muchas preguntas (a menudo vinculadas a Barras de orden en el gráfico de barras ggplot2 ) sobre cómo (re) ordenar categorías en un diagrama de barra.

Lo que busco es solo un toque diferente, pero no he encontrado una buena manera de hacerlo: tengo un gráfico de barras multifacético, y quiero ordenar el eje x para cada faceta de forma independiente, de acuerdo con otra variable ( en mi caso, esa variable es solo el valor y en sí, es decir, solo quiero que las barras vayan en longitud creciente en cada faceta).

Ejemplo simple, siguiendo, por ejemplo, Barras de orden en el gráfico de barras ggplot2 :

df <- data.frame(name=c(''foo'',''bar'',''foo'',''bar''),period=c(''old'',''old'',''recent'',''recent''),val=c(1.23,2.17,4.15,3.65)) p = ggplot(data = df, aes(x = reorder(name, val), y = val)) p = p + geom_bar(stat=''identity'') p = p + facet_grid(~period) p

Lo que obtenemos es lo siguiente:

Mientras que lo que quiero es:


Hay varias maneras diferentes de lograr el objetivo de OP para esta respuesta

(1) reorder_within() funciona para reordenar el name dentro de las facetas del period .

library(tidyverse) library(forcats) df <- data.frame( name = c("foo", "bar", "foo", "bar"), period = c("old", "old", "recent", "recent"), val = c(1.23, 2.17, 4.15, 3.65) ) reorder_within <- function(x, by, within, fun = mean, sep = "___", ...) { new_x <- paste(x, within, sep = sep) stats::reorder(new_x, by, FUN = fun) } scale_x_reordered <- function(..., sep = "___") { reg <- paste0(sep, ".+$") ggplot2::scale_x_discrete(labels = function(x) gsub(reg, "", x), ...) } ggplot(df, aes(reorder_within(name, val, period), val)) + geom_col() + scale_x_reordered() + facet_grid(period ~ ., scales = "free", space = "free") + coord_flip() + theme_minimal() + theme(panel.grid.major.y = element_blank())

O (2) idea similar

### https://trinkerrstuff.wordpress.com/2016/12/23/ordering-categories-within-ggplot2-facets/ df %>% mutate(name = reorder(name, val)) %>% group_by(period, name) %>% arrange(desc(val)) %>% ungroup() %>% mutate(name = factor(paste(name, period, sep = "__"), levels = rev(paste(name, period, sep = "__")))) %>% ggplot(aes(name, val)) + geom_col() + facet_grid(period ~., scales = "free", space = ''free'') + scale_x_discrete(labels = function(x) gsub("__.+$", "", x)) + coord_flip() + theme_minimal() + theme(panel.grid.major.y = element_blank()) + theme(axis.ticks.y = element_blank())

O (3) ordena todo el marco de datos y también ordena las categorías ( period ) dentro de cada grupo de facetas

### https://drsimonj.svbtle.com/ordering-categories-within-ggplot2-facets # df2 <- df %>% # 1. Remove any grouping ungroup() %>% # 2. Arrange by # i. facet group (period) # ii. value (val) arrange(period, val) %>% # 3. Add order column of row numbers mutate(order = row_number()) df2 #> name period val order #> 1 foo old 1.23 1 #> 2 bar old 2.17 2 #> 3 bar recent 3.65 3 #> 4 foo recent 4.15 4 ggplot(df2, aes(order, val)) + geom_col() + facet_grid(period ~ ., scales = "free", space = "free") + coord_flip() + theme_minimal() + theme(panel.grid.major.y = element_blank())

# To finish we need to replace the numeric values on each x-axis # with the appropriate labels ggplot(df2, aes(order, val)) + geom_col() + scale_x_continuous( breaks = df2$order, labels = df2$name) + # scale_y_continuous(expand = c(0, 0)) + facet_grid(period ~ ., scales = "free", space = "free") + coord_flip() + theme_minimal() + theme(panel.grid.major.y = element_blank()) + theme(legend.position = "bottom", axis.ticks.y = element_blank())

Creado en 2018-11-05 por el paquete reprex (v0.2.1.9000)


Ok, así que deja de lado la filosofía, y en caso de que alguien esté interesado, aquí hay un feo truco para hacerlo. La idea es usar etiquetas diferentes (piense en paste(period, name) excepto que reemplacé el período en espacio 0, espacio 1, etc. para que no aparezcan). Necesito esta trama y no quiero organizar grobs y similares, porque tal vez quiera compartir una leyenda común, etc.

El ejemplo atómico dado anteriormente se convierte en:

df <- data.frame(name=c(''foo'',''bar'',''foo'',''bar''), period=c(''old'',''old'',''recent'',''recent''), val=c(1.23,2.17,4.15,3.65), stringsAsFactors=F) df$n = as.numeric(factor(df$period)) df = ddply(df,.(period,name),transform, x=paste(c(rep('' '',n-1), name), collapse='''')) df$x = factor(df$x, levels=df[order(df$val), ''x'']) p = ggplot(data = df, aes(x = x, y = val)) p = p + geom_bar(stat=''identity'') p = p + facet_grid(~period, scale=''free_x'') p

Otro ejemplo, aún un poco tonto pero más cercano a mi caso de uso real, sería:

df <- ddply(mpg, .(year, manufacturer), summarize, mixmpg = mean(cty+hwy)) df$manufacturer = as.character(df$manufacturer) df$n = as.numeric(factor(df$year)) df = ddply(df, .(year,manufacturer), transform, x=paste(c(rep('' '',n-1), manufacturer), collapse='''')) df$x = factor(df$x, levels=df[order(df$mixmpg), ''x'']) p = ggplot(data = df, aes(x = x, y = mixmpg)) p = p + geom_bar(stat=''identity'') p = p + facet_grid(~year, scale=''free_x'') p = p + theme(axis.text.x=element_text(angle=90,hjust=1,vjust=.5,colour=''gray50'')) p

Cierra los ojos, piensa en el Imperio y trata de disfrutar.


Prueba esto, es muy simple (solo ignora las advertencias)

df <-data.frame(name = c(''foo'', ''bar'', ''foo'', ''bar''), period = c(''old'', ''old'', ''recent'', ''recent''), val = c(1.23, 2.17, 4.15, 3.65)) d1 <- df[order(df$period, df$val), ] sn <- factor(x = 1:4, labels = d1$name) d1$sn <- sn p <- ggplot(data = d1, aes(x = sn, y = val)) p <- p + geom_bar(stat = ''identity'') p <- p + facet_wrap(~ period, scale = ''free_x'') p