r ggplot2

Gráfico de barras apiladas, orden de relleno independiente para cada pila



ggplot2 (3)

Me enfrento a un comportamiento de ggplot2 , ordenando y gráfico de barras apilado que no puedo entender.
He leído algunas preguntas al respecto ( here , here y así sucesivamente), pero desafortunadamente no puedo encontrar una solución que se adapte a mí. Tal vez la respuesta sea fácil y no la pueda ver. Espero que no sea un tonto.

Mi objetivo principal es tener cada pila ordenada de forma independiente, en función de la columna de ordenación (llamada aquí ordering ).

Aquí tengo algunos datos:

library(dplyr) library(ggplot2) dats <- data.frame(id = c(1,1,1,2,2,3,3,3,3), value = c(9,6,4,5,6,4,3,4,5), ordering = c(1,2,3,2,3,1,3,2,4), filling = c(''a'',''b'',''c'',''b'',''a'',''a'',''c'',''d'',''b'')) %>% arrange(id,ordering)

Por lo tanto, hay una ID, un valor, un valor que se utiliza para ordenar y un relleno, los datos son los que deben ordenarse en el gráfico, como en la columna de ordering .

Intenté trazarlo: la idea es trazar como un gráfico de barras apiladas con el eje x el id , el valor del value , rellenado por el filling , pero el relleno tiene como orden el valor del ordering , en un orden ascendente, es decir , el mayor valor del ordering en la parte inferior de cada columna . El orden del filling es algo igual que el conjunto de datos, es decir, cada columna tiene un orden independiente.

Como puedes imaginar, son datos falsos, por lo que el número de ID puede variar.

id value ordering filling 1 1 9 1 a 2 1 6 2 b 3 1 4 3 c 4 2 5 2 b 5 2 6 3 a 6 3 4 1 a 7 3 4 2 d 8 3 3 3 c 9 3 5 4 b

Cuando los trazo, hay algo que no entiendo:

library(dplyr) dats$filling <- reorder(dats$filling, -dats$ordering) ggplot(dats,aes(x = id, y = value, fill = filling)) + geom_bar(stat = "identity",position = "stack") + guides(fill=guide_legend("ordering"))

La segunda y la tercera identificación no están correctamente ordenadas, debería tener el orden del conjunto de datos original.


El problema aquí es que el elemento filling = d solo aparece en el tercer grupo con un valor bajo. Una solución, podría ser llenar valores no presentes con 0:

library(dplyr) #> #> Attachement du package : ''dplyr'' #> The following objects are masked from ''package:stats'': #> #> filter, lag #> The following objects are masked from ''package:base'': #> #> intersect, setdiff, setequal, union library(ggplot2) dats <- data.frame(id = c(1,1,1,1,2,2,2,2,3,3,3,3), value = c(9,6,4,0,5,6,0,0,4,3,4,5), ordering = c(1,2,3,5,2,3,5,5,1,3,2,4), filling = c(''a'',''b'',''c'',''d'',''b'',''a'',''c'',''d'',''a'',''c'',''d'',''b'')) %>% arrange(id,ordering) ggplot(dats,aes(x = id, y = value, fill = reorder(filling,-ordering))) + geom_bar(stat = "identity",position = "stack") + guides(fill=guide_legend("ordering"))

Creado en 2018-12-03 por el paquete reprex (v0.2.1)


El problema es que, en su caso, las barras diferentes deben usar los mismos valores (niveles) de filling en un orden diferente. Esto entra en conflicto con la forma en que funciona ggplot : tomar los niveles de factor (que ya tienen un cierto orden) y aplicarlos de la misma manera para cada barra.

Una solución es entonces ... Para crear muchos niveles de factores.

ggplot(dats, aes(x = id, y = value, fill = interaction(-ordering, id))) + geom_bar(stat = "identity", position = "stack")

Este ahora es demasiado "generoso" por ser demasiado detallado. Sin embargo, lo que podemos hacer ahora es lidiar con la leyenda y los diferentes colores:

dats <- arrange(dats, id, -ordering) aux <- with(dats, match(sort(unique(filling)), filling)) ggplot(dats, aes(x = id, y = value, fill = interaction(-ordering, id))) + geom_bar(stat = "identity", position = "stack") + scale_fill_manual("Ordering", values = scales::hue_pal()(4)[dats$filling], labels = with(dats, filling[aux]), breaks = with(dats, interaction(-ordering, id)[aux]))

Aquí primero reorganizo las filas de dats para evitar hacerlo más tarde. Entonces aux es un vector auxiliar

aux # [1] 3 2 1 8

dando posiciones arbitrarias (una para cada una) donde los niveles a , b , c y d (en este orden) aparecen en dats , que de nuevo es útil más adelante. Luego simplemente establezco valores de escala, etiquetas y saltos correspondientes ... Por último, uso scales::hue_pal para recuperar la paleta de colores original.


Si usa geom_bar s por separado, puede hacer que los pedidos sean diferentes.

dats %>% ggplot(aes(x = id, y = value, fill = reorder(filling,-ordering))) + geom_bar(stat = "identity", position = "stack", data = dats %>% filter(id == 1)) + geom_bar(stat = "identity", position = "stack", data = dats %>% filter(id == 2)) + geom_bar(stat = "identity", position = "stack", data = dats %>% filter(id == 3)) + guides(fill=guide_legend("ordering"))

Más generalmente:

bars <- map(unique(dats$id) , ~geom_bar(stat = "identity", position = "stack" , data = dats %>% filter(id == .x))) dats %>% ggplot(aes(x = id, y = value, fill = reorder(filling,-ordering))) + bars + guides(fill=guide_legend("ordering"))