GOOGLE ADS

viernes, 22 de abril de 2022

¿Cómo fusionar leyendas con múltiples scale_identity (ggplot2)?

I am trying to make a series of line plots. Units (name) have repeated observations (x, y). Because in my real data set I have more units (~35) than feasible colors or shapes, I want to cycle first through colors and then cycle through shapes (i.e. blue circle, red circle, blue triangle, red triangle, etc.).

library(tidyverse)
df <- data.frame(name = c('a','a','b','b','c','c'),
x = c(1,5,1,3,3,4),
y = c(1,3,2,1,3,2))
df %>%
ggplot(aes(x = x, y = y, color = name, shape = name)) +
geom_line() +
geom_point() +
scale_color_manual(values = c('blue', 'red', 'blue')) +
scale_shape_manual(values = c(16,16,17))

ingrese la descripción de la imagen aquí

Para evitar confusiones, en varias parcelas me gustaría que las unidades tuvieran la misma estética. Sin embargo, debido a que diferentes parcelas contienen diferentes combinaciones de unidades, los métodos básicos de escalado en ggplot2 asignan una estética diferente a cada unidad en todas las parcelas. Por ejemplo, en el diagrama de arriba, 'c' es un triángulo azul, y en el diagrama de abajo, 'c' es un círculo rojo:

df %>% 
filter(name %in% c('a','c')) %>%
ggplot(aes(x = x, y = y, color = name, shape = name)) +
geom_line() +
geom_point() +
scale_color_manual(values = c('blue', 'red', 'blue')) +
scale_shape_manual(values = c(16,16,17))

ingrese la descripción de la imagen aquí

Soy consciente de que puedo definir manualmente la estética de cada unidad en cada parcela, pero esto es tedioso y propenso a errores. La forma más sencilla y segura de manejar el problema parece ser usar scale_identity, con columnas en mi marco de datos que contienen valores estéticos:

df <- df %>% 
mutate(colors = c('blue','blue','red','red','blue','blue'),
shapes = c(16,16,16,16,17,17))
df %>%
ggplot(aes(x = x, y = y, color = colors, shape = shapes, group = name)) +
geom_line() +
geom_point() +
scale_color_identity(guide = 'legend') +
scale_shape_identity(guide = 'legend') +
labs(color = 'name', shape = 'name')

ingrese la descripción de la imagen aquí

Este método produce una estética consistente en todas las parcelas y es escalable a muchas unidades. Pero me gustaría que la leyenda se fusionara, como en la primera trama. Específicamente, quiero una clave para cada unidad que muestre la intersección de color/forma y una etiqueta para cada clave correspondiente al nombre. ¿Hay alguna forma de hacer esto?


Solución del problema

Creo que scale_color_manual es el camino a seguir aquí debido a su versatilidad. Sus preocupaciones sobre la repetición y la mantenibilidad están justificadas, pero la solución es mantener un marco de datos separado de asignaciones estéticas:

library(tidyverse)
df <- data.frame(name = c('a','a','b','b','c','c'),
x = c(1,5,1,3,3,4),
y = c(1,3,2,1,3,2))
scale_map <- data.frame(name = c("a", "b", "c"),
color = c("blue", "red", "blue"),
shape = c(16, 16, 17))
df %>%
ggplot(aes(x = x, y = y, color = name, shape = name)) +
geom_line() +
geom_point(size = 3) +
scale_color_manual(values = scale_map$color, labels = scale_map$name,
name = "name") +
scale_shape_manual(values = scale_map$shape, labels = scale_map$name,
name = "name")

Creado el 2022-04-15 por el paquete reprex (v2.0.1)

No hay comentarios:

Publicar un comentario

Regla de Firestore para acceder a la generación de subcolección Permisos faltantes o insuficientes

Tengo problemas con las reglas de Firestore para permitir el acceso a algunos recursos en una subcolección. Tengo algunos requests document...