Cómo asignar dos escalas diferentes para una misma estética en ggplot

El post de hoy sea quizás uno de los más especiales de todo el Calendario de adviento 2021. Para la entrada de hoy necesitaremos tener instaladas, además de la librería ggplot2, la librería ggnewscale.

En ocasiones, cuando el gráfico se vuelve muy complejo, con varias capas, la modificación de los elementos básicos no suele ser tan sencilla. Uno de los casos más particulares, es cuando tenemos dos variables que se asignan a la misma estética, pero a las cuales le queremos asignar una escala diferente. Esto suele ocurrir, especialemente al trabajar con varias geometrías. Veamos un ejemplo.

library(ggplot2)
library(showtext)
font_add_google('Anton')

msleep$vore <- as.factor(msleep$vore)
levels(msleep$vore) <- c('carnívoro', 'herbívoro', 'insectívoro', 'omnívoro')

ggplot(msleep, aes(x=sleep_total, y=sleep_rem, color=vore)) +      
  labs(title='El sueño de los mamíferos', 
       subtitle='Sueño REM frente a las horas totales de sueño', 
       caption='Proceedings of the National Academy of Sciences, 104 (3):1051-1056, 2007',
       x='Horas de sueño en total', y='Horas de sueño en fase REM') + 
  theme(plot.title=element_text(family='Anton', size=20),
        plot.subtitle=element_text(family='Anton'),
        axis.title.x = element_text(family='Anton', face='bold', hjust=1),
        axis.title.y = element_text(family='Anton', face='bold', hjust=1),
        strip.text=element_text(family='Anton', face='bold', size=14, hjust=0, color='white'),
        strip.background=element_rect(fill='black')) +
  facet_wrap('vore') +
  theme() -> p
my_colors <- c('#DCB0F2','#87C55F','#9EB9F3','#FE88B1','#C9DB74')
p + 
  geom_point() +
  scale_color_manual(values=my_colors) 

Imaginemos que sobre estos puntos queremos trazar una línea de suavizado, con geom_smooth(), de un color ligeramente más oscuro a los puntos, para discernirla mejor. La librería shades permite modificar el brillo del color con la función brightness() muy fácilmente. Pero veamos qué ocurre al añadirla.

library(shades)
p + 
  geom_point() +
  scale_color_manual(values=my_colors) +
  geom_smooth(se = F) +
  scale_color_manual(values=brightness(my_colors, 0.5))
## Scale for 'colour' is already present. Adding another scale for 'colour',
## which will replace the existing scale.
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

Si nos fijamos, ggplot toma la última escala de colores que se indique e ignora todas las anteriores. Entonces, ¿cómo podríamos asignar dos escalas diferentes a una misma estética como el color? La respuesta nos la da la librería ggnewscale. Esta librería permite redefinir la escala de color, fill, size, alpha, o cualquier otra estética que deseemos a través de la función new_scale_color().

library(ggnewscale)
p + 
  geom_point() +
  scale_color_manual(values=my_colors) +
  new_scale_color() +
  geom_smooth(aes(color=vore), se = F) +
  scale_color_manual(values=brightness(my_colors, 0.5))
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

Recuerda que debes mapear de nuevo la variable que corresponda al color, ya que resetea por completo esta característica.

Para cualquier otra estética, simplemente utiliza new_scale("...") e indica el nombre la misma entre comillas.

En resumen…

  • Para resetear la escala de color utiliza new_scale_color()

  • Para cualquier otra estética utiliza new_scale('...') indicando el nombre de la estética (fill, alpha, size, etc)

Paula L. Casado
Paula L. Casado
Data Scientist

Científica de datos especializada en visualización de datos.

Relacionado