17  Temas

You are reading the work-in-progress third edition of the ggplot2 book. This chapter is currently a dumping ground for ideas, and we don’t recommend reading it.

17.1 Introducción

En este capítulo aprenderá a utilizar el sistema de temas ggplot2, que le permite ejercer un control preciso sobre los elementos que no son datos de su gráfica. El sistema de temas no afecta la forma en que las geoms representan los datos ni cómo se transforman mediante las escalas. Los temas no cambian las propiedades de percepción de la gráfica, pero sí te ayudan a hacer que la gráfica sea estéticamente agradable o que coincida con una guía de estilo existente. Los temas te dan control sobre cosas como fuentes, ticks, franjas de paneles y fondos.

Esta separación del control en partes de datos y partes que no son de datos es bastante diferente de los gráficos base y reticulares. En los gráficos base y reticular, la mayoría de las funciones toman una gran cantidad de argumentos que especifican la apariencia tanto de datos como de no datos, lo que hace que las funciones sean complicadas y difíciles de aprender. ggplot2 adopta un enfoque diferente: al crear el gráfico, usted determina cómo se muestran los datos, luego, después de haberlos creado, puede editar cada detalle de la representación, utilizando el sistema de temas.

El sistema de tematización se compone de cuatro componentes principales:

  • Los elementos del tema especifican los elementos que no son datos que puedes controlar. Por ejemplo, el elemento plot.title controla la apariencia del título de la gráfica; axis.ticks.x, los ticks en el eje x; legend.key.height, la altura de las claves en la leyenda.

  • Cada elemento está asociado con una función del elemento, que describe las propiedades visuales del elemento. Por ejemplo, element_text() establece el tamaño de fuente, el color y el aspecto de elementos de texto como plot.title.

  • La función theme() que le permite anular los elementos predeterminados del tema llamando a funciones de elementos, como theme(plot.title = element_text(colour = "red")).

  • Temas completos, como theme_grey(), configuran todos los elementos del tema con valores diseñados para trabajar juntos armoniosamente.

Por ejemplo, imagina que has hecho el siguiente gráfico de tus datos.

base <- ggplot(mpg, aes(cty, hwy, color = factor(cyl))) +
  geom_jitter() + 
  geom_abline(colour = "grey50", size = 2)
#> Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
#> ℹ Please use `linewidth` instead.
base

Ha cumplido su propósito para usted: ha aprendido que cty y hwy están altamente correlacionados, ambos están estrechamente acoplados con cyl y que hwy siempre es mayor que cty (y la diferencia aumenta a medida que cty aumenta). Ahora quieres compartir la gráfica con otros, tal vez publicándola en un periódico. Eso requiere algunos cambios. Primero, debes asegurarte de que la gráfica pueda funcionar por sí sola mediante:

  • Mejora de los ejes y etiquetas de leyenda.
  • Agregar un título para la gráfica.
  • Ajustar la escala de colores.

Afortunadamente, ya sabes cómo hacerlo porque has leído Sección 8.1 y ?sec-scale-color:

labelled <- base +
  labs(
    x = "Kilometraje en ciudad/galón",
    y = "Kilometraje en carretera/galón",
    colour = "Cilindros",
    title = "El kilometraje en carretera y en ciudad están altamente correlacionados"
  ) +
  scale_colour_brewer(type = "seq", palette = "Spectral")
labelled

A continuación, debes asegurarte de que la gráfica coincida con las pautas de estilo de tu revista:

  • El fondo debe ser blanco, no gris pálido.
  • La leyenda debe colocarse dentro de la gráfica si hay espacio.
  • Las líneas de división principales deben ser de color gris pálido y las líneas de división menores deben eliminarse.
  • El título de la gráfica debe ser texto en negrita de 12 puntos.

En este capítulo, aprenderá cómo utilizar el sistema de temas para realizar esos cambios, como se muestra a continuación:

styled <- labelled +
  theme_bw() + 
  theme(
    plot.title = element_text(face = "bold", size = 12),
    legend.background = element_rect(
      fill = "white", 
      linewidth = 4, 
      colour = "white"
    ),
    legend.justification = c(0, 1),
    legend.position = c(0, 1),
    axis.ticks = element_line(colour = "grey70", linewidth = 0.2),
    panel.grid.major = element_line(colour = "grey70", linewidth = 0.2),
    panel.grid.minor = element_blank()
  )
#> Warning: A numeric `legend.position` argument in `theme()` was deprecated in ggplot2
#> 3.5.0.
#> ℹ Please use the `legend.position.inside` argument of `theme()` instead.
styled

Finalmente, la revista quiere la figura en un archivo TIFF de 600 ppp. Aprenderá los detalles finos de ggsave() en ?sec-served.

17.2 Temas completos

ggplot2 viene con varios temas integrados. El más importante es theme_grey(), el tema característico de ggplot2 con un fondo gris claro y líneas de cuadrícula blancas. El tema está diseñado para presentar los datos y al mismo tiempo respaldar las comparaciones, siguiendo el consejo de (Tufte 2006; cervecero? 1994; Carr 2002, 1994; Carr y Sun 1999). Todavía podemos ver las líneas de la cuadrícula para ayudarnos a juzgar la posición (Cleveland 1993), pero tienen poco impacto visual y podemos “desconectarnos” fácilmente de ellas. El fondo gris le da a la gráfica un color tipográfico similar al del texto, asegurando que los gráficos encajen con el flujo de un documento sin saltar con un fondo blanco brillante. Finalmente, el fondo gris crea un campo continuo de color que asegura que la gráfica se perciba como una única entidad visual.

Hay otros siete temas integrados en ggplot2 1.1.0:

  • theme_bw(): una variación de theme_grey() que utiliza un fondo blanco y finas líneas de cuadrícula grises.

  • theme_linedraw(): un tema con sólo líneas negras de varios anchos sobre fondos blancos, que recuerda a un dibujo lineal.

  • theme_light(): similar a theme_linedraw() pero con líneas y ejes de color gris claro, para dirigir más atención hacia los datos.

  • theme_dark(): el primo oscuro de theme_light(), con tamaños de línea similares pero con un fondo oscuro. Útil para hacer resaltar líneas finas de colores.

  • theme_minimal(): un tema minimalista sin anotaciones de fondo.

  • theme_classic(): un tema de aspecto clásico, con líneas de eje x e y y sin líneas de cuadrícula.

  • theme_void(): un tema completamente vacío.

df <- data.frame(x = 1:3, y = 1:3)
base <- ggplot(df, aes(x, y)) + geom_point()
base + theme_grey() + ggtitle("theme_grey()")
base + theme_bw() + ggtitle("theme_bw()")
base + theme_linedraw() + ggtitle("theme_linedraw()")

base + theme_light() + ggtitle("theme_light()")
base + theme_dark() + ggtitle("theme_dark()")
base + theme_minimal()  + ggtitle("theme_minimal()")

base + theme_classic() + ggtitle("theme_classic()")
base + theme_void() + ggtitle("theme_void()")

Todos los temas tienen un parámetro base_size que controla el tamaño de fuente base. El tamaño de fuente base es el tamaño que utilizan los títulos de los ejes: el título de la gráfica suele ser más grande (1,2x) y las etiquetas de marca y tira son más pequeñas (0,8x). Si desea controlar estos tamaños por separado, deberá modificar los elementos individuales como se describe a continuación.

Además de aplicar temas en un argumento a la vez, puedes cambiar el tema predeterminado con theme_set(). Por ejemplo, si realmente odias el fondo gris predeterminado, ejecuta theme_set(theme_bw()) para usar un fondo blanco para todos los gráficos.

No estás limitado a los temas integrados en ggplot2. Otros paquetes, como ggthemes de Jeffrey Arnold, añaden aún más. Estos son algunos de mis favoritos de ggthemes:

library(ggthemes)
base + theme_tufte() + ggtitle("theme_tufte()")
base + theme_solarized() + ggtitle("theme_solarized()")
base + theme_excel() + ggtitle("theme_excel()") # ;)

Los temas completos son un excelente lugar para comenzar, pero no te dan mucho control. Para modificar elementos individuales, necesita usar theme() para anular la configuración predeterminada para un elemento con una función de elemento.

17.2.1 Ejercicios

  1. Pruebe todos los temas en ggthemes. ¿Cuál te gusta más?

  2. ¿Qué aspectos del tema predeterminado te gustan? ¿Qué no te gusta?
    ¿Qué cambiarías?

  3. Mira los argumentos de tu revista científica favorita. ¿A qué tema se parecen más? ¿Cuáles son las principales diferencias?

17.3 Modificar componentes del tema

Para modificar un componente de tema individual, utiliza un código como plot + theme(element.name = element_function()). En esta sección aprenderá sobre las funciones básicas de los elementos y luego, en la siguiente sección, verá todos los elementos que puede modificar.

Hay cuatro tipos básicos de funciones de elementos integradas: texto, líneas, rectángulos y espacios en blanco. Cada elemento función tiene un conjunto de parámetros que controlan la apariencia:

  • element_text() Dibuja etiquetas y títulos. Puede controlar la fuente family, face, colour, size (en puntos), hjust, vjust, angle (en grados) y lineheight (como proporción de fontcase). Se pueden encontrar más detalles sobre los parámetros en vignette("ggplot2-specs"). Configurar la fuente es particularmente desafiante.

    base_t <- base + labs(title = "Este es un ggplot") + xlab(NULL) + ylab(NULL)
    base_t + theme(plot.title = element_text(size = 16))
    base_t + theme(plot.title = element_text(face = "bold", colour = "red"))
    base_t + theme(plot.title = element_text(hjust = 1))

    Puede controlar los márgenes alrededor del texto con el argumento margin y la función margin(). margin() tiene cuatro argumentos: la cantidad de espacio (en puntos) que se agregará a los lados superior, derecho, inferior e izquierdo del texto. Cualquier elemento no especificado tiene el valor predeterminado 0.

    # Los márgenes aquí parecen asimétricos porque también hay márgenes de gráfica.
    base_t + theme(plot.title = element_text(margin = margin()))
    base_t + theme(plot.title = element_text(margin = margin(t = 10, b = 10)))
    base_t + theme(axis.title.y = element_text(margin = margin(r = 10)))

  • element_line() dibuja líneas parametrizadas por colour, linewidth y linetype:

    base + theme(panel.grid.major = element_line(colour = "black"))
    base + theme(panel.grid.major = element_line(linewidth = 2))
    base + theme(panel.grid.major = element_line(linetype = "dotted"))

  • element_rect() Dibuja rectángulos, utilizados principalmente para fondos, parametrizados por fill color y borde colour, linewidth y linetype.

    base + theme(plot.background = element_rect(fill = "grey80", colour = NA))
    base + theme(plot.background = element_rect(colour = "red", linewidth = 2))
    base + theme(panel.background = element_rect(fill = "linen"))

  • element_blank() no dibuja nada. Utilízalo si no quieres que se dibuje nada y que no se asigne espacio para ese elemento. El siguiente ejemplo utiliza element_blank() para suprimir progresivamente la apariencia de elementos que no nos interesan. Observe cómo la gráfica recupera automáticamente el espacio utilizado previamente por estos elementos: si no desea que esto suceda (tal vez porque necesita alinearse con otros gráficos en la página), use colour = NA, fill = NA para crear elementos invisibles que aún ocupan espacio.

    base
    last_plot() + theme(panel.grid.minor = element_blank())
    last_plot() + theme(panel.grid.major = element_blank())

    last_plot() + theme(panel.background = element_blank())
    last_plot() + theme(
      axis.title.x = element_blank(), 
      axis.title.y = element_blank()
    )
    last_plot() + theme(axis.line = element_line(colour = "grey50"))

  • Algunas otras configuraciones toman unidades de cuadrícula. Créelos con unit(1, "cm") o unit(0.25, "in").

Para modificar los elementos del tema para todas las gráficas futuras, use theme_update(). Devuelve la configuración del tema anterior, por lo que puedes restaurar fácilmente los parámetros originales una vez que hayas terminado.

old_theme <- theme_update(
  plot.background = element_rect(fill = "lightblue3", colour = NA),
  panel.background = element_rect(fill = "lightblue", colour = NA),
  axis.text = element_text(colour = "linen"),
  axis.title = element_text(colour = "linen")
)
base
theme_set(old_theme)
base

17.4 Elementos temáticos

Hay alrededor de 40 elementos únicos que controlan la apariencia de la gráfica. Se pueden agrupar a grandes rasgos en cinco categorías: gráfica, eje, leyenda, panel y faceta. Las siguientes secciones describen cada uno de ellos por separado.

17.4.1 Elementos de la gráfica

Algunos elementos afectan la gráfica en su conjunto:

Elemento Setter Descripción
plot.background element_rect() fondo de la gráfica
plot.title element_text() título de la gráfica
plot.margin margin() márgenes alrededor de la gráfica

plot.background dibuja un rectángulo que subyace a todo lo demás en el gráfico. De forma predeterminada, ggplot2 usa un fondo blanco que garantiza que el gráfico se pueda utilizar dondequiera que termine (por ejemplo, incluso si lo guarda como png y lo coloca en una diapositiva con un fondo negro). Al exportar gráficos para utilizarlos en otros sistemas, es posible que desee hacer que el fondo sea transparente con fill = NA. De manera similar, si está incrustando un gráfico en un sistema que ya tiene márgenes, es posible que desee eliminar los márgenes integrados. Tenga en cuenta que aún es necesario un pequeño margen si desea dibujar un borde alrededor del gráfico.

base + theme(plot.background = element_rect(colour = "grey50", linewidth = 2))
base + theme(
  plot.background = element_rect(colour = "grey50", linewidth = 2),
  plot.margin = margin(2, 2, 2, 2)
)
base + theme(plot.background = element_rect(fill = "lightblue"))

17.4.2 Elementos del eje

Los elementos de eje controlan la apariencia de los ejes:

Elemento Setter Descripción
axis.line element_line() Línea paralela al eje (oculta en temas predeterminados)
axis.text element_text() etiquetas de marca
axis.text.x element_text() etiquetas de marca del eje x
axis.text.y element_text() etiquetas de marca del eje y
axis.title element_text() títulos de eje
axis.title.x element_text() título del eje x
axis.title.y element_text() título del eje y
axis.ticks element_line() marcas de eje
axis.ticks.length unit() longitud de las marcas de graduación

Tenga en cuenta que axis.text (y axis.title) viene en tres formas: axis.text, axis.text.x y axis.text.y. Utilice la primera forma si desea modificar las propiedades de ambos ejes a la vez: cualquier propiedad que no establezca explícitamente en axis.text.x y axis.text.y se heredará de axis.text.

df <- data.frame(x = 1:3, y = 1:3)
base <- ggplot(df, aes(x, y)) + geom_point()

# Acentuar los ejes
base + theme(axis.line = element_line(colour = "grey50", linewidth = 1))
# Aplicar estilo a las etiquetas de los ejes x e y
base + theme(axis.text = element_text(color = "blue", size = 12))
# Útil para etiquetas largas
base + theme(axis.text.x = element_text(angle = -90, vjust = 0.5))

El ajuste más común es rotar las etiquetas del eje x para evitar etiquetas superpuestas durante mucho tiempo. Si hace esto, tenga en cuenta que los ángulos negativos tienden a verse mejor y debe establecer hjust = 0 y vjust = 1:

df <- data.frame(
  x = c("label", "a long label", "an even longer label"), 
  y = 1:3
)
base <- ggplot(df, aes(x, y)) + geom_point()
base
base + 
  theme(axis.text.x = element_text(angle = -30, vjust = 1, hjust = 0)) + 
  xlab(NULL) + 
  ylab(NULL)

17.4.3 Elementos de leyenda

Los elementos de leyenda controlan la apariencia de todas las leyendas. También puede modificar la apariencia de leyendas individuales modificando los mismos elementos en guide_legend() o guide_colourbar().

Elemento Setter Descripción
legend.background element_rect() fondo de leyenda
legend.key element_rect() fondo de claves de leyenda
legend.key.size unit() tamaño de clave de leyenda
legend.key.height unit() altura de la clave de leyenda
legend.key.width unit() ancho de clave de leyenda
legend.margin unit() margen de leyenda
legend.text element_text() etiquetas de leyenda
legend.text.align 0–1 alineación de la etiqueta de la leyenda (0 = right, 1 = left)
legend.title element_text() nombre de la leyenda
legend.title.align 0–1 alineación del nombre de la leyenda (0 = right, 1 = left)

Estas opciones se ilustran a continuación:

df <- data.frame(x = 1:4, y = 1:4, z = rep(c("a", "b"), each = 2))
base <- ggplot(df, aes(x, y, colour = z)) + geom_point()

base + theme(
  legend.background = element_rect(
    fill = "lemonchiffon", 
    colour = "grey50", 
    linewidth = 1
  )
)
base + theme(
  legend.key = element_rect(color = "grey50"),
  legend.key.width = unit(0.9, "cm"),
  legend.key.height = unit(0.75, "cm")
)
base + theme(
  legend.text = element_text(size = 15),
  legend.title = element_text(size = 15, face = "bold")
)

Hay otras cuatro propiedades que controlan cómo se disponen las leyendas en el contexto de la gráfica (legend.position, legend.direction, legend.justification, legend.box). Se describen en Sección 11.7.

17.4.4 Elementos del panel

Los elementos del panel controlan la apariencia de los paneles de trazado:

Elemento Setter Descripción
panel.background element_rect() fondo del panel (bajo datos)
panel.border element_rect() borde del panel (sobre datos)
panel.grid.major element_line() líneas principales de la cuadrícula
panel.grid.major.x element_line() líneas verticales principales de la cuadrícula
panel.grid.major.y element_line() líneas de cuadrícula principales horizontales
panel.grid.minor element_line() líneas de cuadrícula menores
panel.grid.minor.x element_line() líneas de cuadrícula menores verticales
panel.grid.minor.y element_line() líneas de cuadrícula menores horizontales
aspect.ratio numeric relación de aspecto de la gráfica

La principal diferencia entre panel.background y panel.border es que el fondo se dibuja debajo de los datos y el borde se dibuja encima. Por esa razón, siempre necesitarás asignar fill = NA al anular panel.border.

base <- ggplot(df, aes(x, y)) + geom_point()
# Modificar fondo
base + theme(panel.background = element_rect(fill = "lightblue"))

# Modificar las principales líneas de la cuadrícula
base + theme(
  panel.grid.major = element_line(color = "gray60", linewidth = 0.8)
)
# Solo en una dirección
base + theme(
  panel.grid.major.x = element_line(color = "gray60", linewidth = 0.8)
)

Tenga en cuenta que la relación de aspecto controla la relación de aspecto del panel, no la gráfica general:

base2 <- base + theme(plot.background = element_rect(colour = "grey50"))
# pantalla ancha
base2 + theme(aspect.ratio = 9 / 16)
# Largo y flaco
base2 + theme(aspect.ratio = 2 / 1)
# Cuadrado
base2 + theme(aspect.ratio = 1)

17.4.5 Elementos facetados

Los siguientes elementos temáticos están asociados con ggplots facetados:

Element Setter Descripción
strip.background element_rect() fondo de tiras de paneles
strip.text element_text() tira de texto
strip.text.x element_text() texto de tira horizontal
strip.text.y element_text() texto de tira vertical
panel.spacing unit() margen entre facetas
panel.spacing.x unit() margen entre facetas (vertical)
panel.spacing.y unit() margen entre facetas (horizontal)

El elemento strip.text.x afecta tanto a facet_wrap() como a facet_grid(); strip.text.y solo afecta facet_grid().

df <- data.frame(x = 1:4, y = 1:4, z = c("a", "a", "b", "b"))
base_f <- ggplot(df, aes(x, y)) + geom_point() + facet_wrap(~z)

base_f
base_f + theme(panel.spacing = unit(0.5, "in"))
base_f + theme(
  strip.text = element_text(colour = "white"),
  strip.background = element_rect(
    fill = "grey20", 
    color = "grey80", 
    linewidth = 1
  )
)

17.4.6 Ejercicios

  1. ¡Crea la gráfica más fea posible! (Aportado por Andrew D. Steen, Universidad de Tennessee - Knoxville)

  2. theme_dark() oscurece el interior de la gráfica, pero no el exterior. Cambie el fondo del trazado a negro y luego actualice la configuración del texto para que aún pueda leer las etiquetas.

  3. Crea un tema elegante que utilice lino como color de fondo y una fuente serif para el texto.

  4. Explora sistemáticamente los efectos de hjust cuando tienes un título de varias líneas. ¿Por qué vjust no hace nada?

17.5 Guardando su salida

Al guardar un trazado para usarlo en otro programa, tiene dos opciones básicas de salida: ráster o vectorial:

  • Los gráficos vectoriales describen una gráfica como una secuencia de operaciones: dibuje una línea desde \((x_1, y_1)\) hasta \((x_2, y_2)\), dibuje un círculo en \((x_3, x_4)\) con radio \(r\). Esto significa que efectivamente se pueden ampliar ‘infinitamente’; no hay pérdida de detalle. Los formatos de gráficos vectoriales más útiles son pdf y svg.

  • Los gráficos rasterizados se almacenan como una variedad de colores de píxeles y tienen un tamaño de visualización óptimo fijo. El formato de gráfico rasterizado más útil es png.

La siguiente figura ilustra las diferencias básicas en estos formatos para un círculo.

The schematic difference between raster (left) and vector (right) graphics.

A menos que haya una razón convincente para no hacerlo, utilice gráficos vectoriales: se ven mejor en más lugares. Hay dos razones principales para utilizar gráficos rasterizados:

  • Tiene un diagrama (por ejemplo, un diagrama de dispersión) con miles de objetos gráficos (es decir, puntos). Una versión vectorial será grande y lenta de renderizar.

  • Quieres incrustar el gráfico en MS Office. MS tiene un soporte deficiente para gráficos vectoriales (a excepción de su propio formato DrawingXML, que actualmente no es fácil de crear desde R), por lo que los gráficos rasterizados son más fáciles.

Hay dos formas de guardar la salida de ggplot2. Puede utilizar el enfoque estándar de R en el que abre un dispositivo gráfico, genera el gráfico y luego cierra el dispositivo:

pdf("output.pdf", width = 6, height = 6)
ggplot(mpg, aes(displ, cty)) + geom_point()
dev.off()
#> png 
#>   2

Esto funciona para todos los paquetes, pero es detallado. ggplot2 proporciona una abreviatura conveniente con ggsave():

ggplot(mpg, aes(displ, cty)) + geom_point()
ggsave("output.pdf")
#> Saving 7 x 5 in image

ggsave() está optimizado para uso interactivo: puedes usarlo después de haber dibujado un diagrama. Tiene los siguientes argumentos importantes:

  • El primer argumento, path, especifica la ruta donde se debe guardar la imagen. La extensión de archivo se utilizará para seleccionar automáticamente el dispositivo gráfico correcto. ggsave() puede producir .eps, .pdf, .svg, .wmf, .png, .jpg, .bmp, y .tiff.

  • width y height controlar el tamaño de salida, especificado en pulgadas. Si se deja en blanco, utilizarán el tamaño del dispositivo gráfico en pantalla.

  • Para gráficos rasterizados (es decir, .png, .jpg), el argumento dpi controla la resolución del gráfico. El valor predeterminado es 300, que es apropiado para la mayoría de las impresoras, pero es posible que desee utilizar 600 para resultados de resolución particularmente alta o 96 para visualización en pantalla (por ejemplo, web).

Consulte ?ggsave para obtener más detalles.

Carr, Dan. 1994. «Using Gray in Plots». ASA Statistical Computing and Graphics Newsletter 2 (5): 11-14. http://www.galaxy.gmu.edu/~dcarr/lib/v5n2.pdf.
———. 2002. «Graphical displays». En Encyclopedia of Environmetrics, editado por Abdel H. El-Shaarawi y Walter W. Piegorsch, 2:933-60. John Wiley & Sons. http://www.galaxy.gmu.edu/~dcarr/lib/EnvironmentalGraphics.pdf.
Carr, Dan, y Ru Sun. 1999. «Using Layering and Perceptual Grouping in Statistical Graphics». ASA Statistical Computing and Graphics Newsletter 10 (1): 25-31.
Cleveland, William. 1993. «A model for studying display methods of statistical graphics». Journal of Computational and Graphical Statistics 2: 323-64. http://stat.bell-labs.com/doc/93.4.ps.
Tufte, Edward R. 2006. Beautiful Evidence. Graphics Press.