Gráficos para comunicar

Introducción

En este capítulo, aprenderás a usar la visualización para comunicar.

En Análisis exploratorio de datos, aprendiste a usar los gráficos como herramientas de exploración. Cuando haces gráficos exploratorios, sabes, incluso antes de mirarlos, qué variables mostrará el gráfico. Hiciste cada gráfico con un propósito, lo miraste rápidamente y luego pasaste al siguiente. En el transcurso de la mayoría de los análisis, producirás decenas o cientos de gráficos, la mayoría de los cuales se descartan de inmediato.

Ahora que entiendes tus datos, necesitas comunicar lo que has comprendido a otras personas. Es probable que tu audiencia no comparta tus conocimientos previos y que no esté muy implicada en los datos. Para ayudar a los demás a construir rápidamente un buen modelo mental de los datos, tendrás que invertir un esfuerzo considerable en que tus gráficos se expliquen por sí mismos tanto como sea posible. En este capítulo, aprenderás algunas de las herramientas que ofrece lets-plot para hacer que los gráficos cuenten una historia.

Requisitos previos

Como siempre, existe una gran cantidad de opciones (y paquetes) para la visualización de datos con código. Aquí nos centramos en el enfoque declarativo de la “gramática de gráficos” con lets-plot, pero los usuarios avanzados que busquen gráficos más complejos quizá prefieran usar una librería imperativa como la excelente matplotlib. Debes tener instalados tanto lets-plot como pandas. Una vez instalados, impórtalos así:

import numpy as np
import pandas as pd
from lets_plot import *

LetsPlot.setup_html()

Etiquetas, títulos y otra información de contexto

El punto de partida más sencillo para convertir un gráfico exploratorio en un gráfico expositivo es usar buenas etiquetas. Veamos un ejemplo con los datos MPG (millas por galón), que recogen el consumo de combustible de 38 modelos populares de automóviles entre 1999 y 2008.

# load the data
mpg = pd.read_csv(
    "https://vincentarelbundock.github.io/Rdatasets/csv/ggplot2/mpg.csv", index_col=0
)

Queremos mostrar cómo cambia la eficiencia de combustible en carretera según la cilindrada del motor, en litros. El gráfico más básico que podemos hacer con estas variables es:

(ggplot(mpg, aes(x="displ", y="hwy")) + geom_point())

Ahora vamos a añadir mucha información adicional útil que mejorará el gráfico. El propósito del título de un gráfico es resumir el hallazgo principal. Evita títulos que solo describan qué es el gráfico, p. ej., “Un scatter plot de la cilindrada del motor frente al consumo de combustible”.

Vamos a:

  • añadir un título que resuma el hallazgo principal que quieres que se lleve quien vea el gráfico (¡en lugar de uno que solo describa lo obvio!)
  • añadir un subtítulo que dé más información sobre el eje y, y hacer más comprensible la etiqueta del eje x
  • eliminar la etiqueta del eje y, que tiene un ángulo de lectura incómodo
  • añadir una leyenda al pie con la fuente de los datos

Con todo esto, obtenemos:

(
    ggplot(mpg, aes(x="displ", y="hwy"))
    + geom_point(aes(colour="class"))
    + geom_smooth(se=False, method="loess", size=1)
    + labs(
        title="La eficiencia de combustible generalmente disminuye con el tamaño del motor",
        subtitle="Eficiencia de combustible en carretera (millas por galón)",
        caption="Fuente: fueleconomy.gov",
        y="",
        x="Cilindrada del motor (litros)",
    )
)

Esto es mucho más claro. Es más fácil de leer, sabemos de dónde provienen los datos y también vemos por qué nos los muestran.

¿Pero y si queremos un mensaje distinto? Puedes adaptarlo según tus necesidades, y algunas personas prefieren tener la etiqueta del eje y girada para que el subtítulo aporte aún más contexto:

(
    ggplot(mpg, aes(x="displ", y="hwy"))
    + geom_point(aes(colour="class"))
    + geom_smooth(se=False, method="loess", size=1)
    + labs(
        x="Cilindrada del motor (L)",
        y="Rendimiento de combustible en carretera (mpg)",
        colour="Tipo de auto",
        title="La eficiencia de combustible generalmente disminuye con el tamaño del motor",
        subtitle="Los biplazas (autos deportivos) son una excepción debido a su bajo peso",
        caption="Fuente: fueleconomy.gov",
    )
)

Ejercicios

  1. Crea un gráfico con los datos de consumo de combustible con etiquetas personalizadas de title, subtitle, caption, x, y y color.

  2. Recrea el siguiente gráfico usando los datos de consumo de combustible. Observa que tanto los colores como las formas de los puntos varían según el tipo de tracción.

  3. Toma un gráfico exploratorio que hayas creado en el último mes y añádele títulos informativos para que a otras personas les resulte más fácil entenderlo.

Anotaciones

Además de etiquetar los componentes principales de tu gráfico, a menudo es útil etiquetar observaciones individuales o grupos de observaciones. La primera herramienta que tienes a tu disposición es geom_text(). geom_text() es similar a geom_point(), pero tiene una estética adicional: label. Esto permite añadir etiquetas de texto a tus gráficos.

Hay dos posibles fuentes de etiquetas: las que forman parte de los datos, que añadiremos con geom_text(), y las que añadimos directa y manualmente como anotaciones con geom_label().

En el primer caso, puede que tengas un dataframe que contenga etiquetas. En el siguiente gráfico extraemos los automóviles con mayor tamaño de motor para cada tipo de tracción y guardamos su información en un nuevo dataframe llamado label_info. Al crearlo, elegimos los valores medios de “hwy” por “drv” como los puntos a etiquetar, pero podríamos hacer cualquier agregación que creamos que funcione bien en el gráfico.

mapping = {
    "4": "4-wheel drive",
    "f": "front-wheel drive",
    "r": "rear-wheel drive",
}
label_info = (
    mpg.groupby("drv")
    .agg({"hwy": "mean", "displ": "mean"})
    .reset_index()
    .assign(drive_type=lambda x: x["drv"].map(mapping))
    .round(2)
)
label_info
drv hwy displ drive_type
0 4 19.17 4.00 4-wheel drive
1 f 28.16 2.56 front-wheel drive
2 r 21.00 5.18 rear-wheel drive

Después, usamos este nuevo dataframe para etiquetar directamente los tres grupos y sustituir la leyenda por etiquetas colocadas directamente sobre el gráfico. Con los argumentos fontface y size podemos personalizar el aspecto de las etiquetas de texto. Son más grandes que el resto del texto del gráfico y están en negrita. (theme(legend.position = "none") desactiva todas las leyendas; hablaremos más de ello en breve).

(
    ggplot(mpg, aes(x="displ", y="hwy", color="drv"))
    + geom_point(alpha=0.5)
    + geom_smooth(se=False, method="loess")
    + geom_text(
        aes(x="displ", y="hwy", label="drive_type"),
        data=label_info,
        fontface="bold",
        size=8,
        hjust="left",
        vjust="bottom",
    )
    + theme(legend_position="none")
)

Observa el uso de hjust (alineación horizontal) y vjust (alineación vertical) para controlar la alineación de la etiqueta.

El segundo de los dos métodos que estamos viendo es geom_label(). Tiene dos modos: en el primero, funciona como geom_text() pero con un recuadro alrededor del texto, así:

potential_outliers = mpg.query("hwy > 40 | (hwy > 20 & displ > 5)")
(
    ggplot(mpg, aes(x="displ", y="hwy"))
    + geom_point(color="black")
    + geom_smooth(se=False, method="loess", color="black")
    + geom_point(
        data=potential_outliers,
        color="red",
    )
    + geom_label(
        aes(label="model"),
        data=potential_outliers,
        color="red",
        position=position_jitter(),
        fontface="bold",
        size=5,
        hjust="left",
        vjust="bottom",
    )
    + theme(legend_position="none")
)

El segundo modo suele ser útil para añadir una o varias anotaciones a un gráfico, así:

import textwrap

# wrap the text so it is over multiple lines:
trend_text = textwrap.fill("Larger engine sizes tend to have lower fuel economy.", 30)
trend_text
'Larger engine sizes tend to\nhave lower fuel economy.'
(
    ggplot(mpg, aes(x="displ", y="hwy"))
    + geom_point()
    + geom_label(x=3.5, y=38, label=trend_text, hjust="left", color="red")
    + geom_segment(x=2, y=40, xend=5, yend=25, arrow=arrow(type="closed"), color="red")
)

Las anotaciones son una herramienta poderosa para comunicar las conclusiones principales y los aspectos interesantes de tus visualizaciones. ¡El único límite es tu imaginación (y tu paciencia para colocar las anotaciones de forma estéticamente agradable)!

Recuerda que, además de geom_text() y geom_label(), tienes muchas otras geoms disponibles en lets-plot para ayudarte a anotar tu gráfico. Un par de ideas:

  • Usa geom_hline() y geom_vline() para añadir líneas de referencia. Solemos hacerlas gruesas (size = 2) y grises (color = gray), y dibujarlas debajo de la capa de datos principal. Así son fáciles de ver, sin desviar la atención de los datos.

  • Usa geom_rect() para dibujar un rectángulo alrededor de los puntos de interés. Los límites del rectángulo se definen con las estéticas xmin, xmax, ymin, ymax.

  • Ya viste el uso de geom_segment() con el argumento arrow para llamar la atención sobre un punto con una flecha. Usa las estéticas x e y para definir la ubicación inicial, y xend e yend para definir la ubicación final.

Ejercicios

  1. Usa geom_text() con posiciones infinitas para colocar texto en las cuatro esquinas del gráfico.

  2. Usa geom_label() para añadir una geom de punto en el centro de tu último gráfico sin tener que crear un dataframe Personaliza la forma, el tamaño o el color del punto.

  3. ¿Cómo interactúan las etiquetas de geom_text() con las facetas? ¿Cómo puedes añadir una etiqueta a una sola faceta? ¿Cómo puedes poner una etiqueta distinta en cada faceta? (Pista: piensa en el dataset que se pasa a geom_text()).

  4. ¿Qué argumentos de geom_label() controlan el aspecto del recuadro de fondo?

  5. ¿Cuáles son los cuatro argumentos de arrow()? ¿Cómo funcionan? Crea una serie de gráficos que muestren las opciones más importantes.

Escalas

Otra forma de mejorar tu gráfico para comunicar es ajustar las escalas. Las escalas controlan cómo se manifiestan visualmente los mapeos estéticos.

Escalas predeterminadas

Normalmente, lets-plot añade automáticamente las escalas por ti y no tienes que preocuparte por ellas. Por ejemplo, cuando escribes:

(
    ggplot(mpg, aes(x="displ", y="hwy")) +
    geom_point(aes(color="class"))
)

lets-plot hace automáticamente esto entre bastidores:

(
    ggplot(mpg, aes(x="displ", y="hwy")) +
    geom_point(aes(color="class")) +
    scale_x_continous() +
    scale_y_continuous() +
    scale_color_discrete()
)

Observa el esquema de nombres de las escalas: scale_ seguido del nombre de la estética, luego _ y luego el nombre de la escala. Las escalas predeterminadas se nombran según el tipo de variable con el que se corresponden: continuous, discrete, datetime o date. scale_x_continuous() coloca los valores numéricos de displ en una recta numérica continua en el eje x, scale_color_discrete() elige colores para cada class de automóvil, etc. Hay muchas escalas no predeterminadas que conocerás a continuación.

Las escalas predeterminadas se han elegido cuidadosamente para funcionar bien con una amplia variedad de entradas. Aun así, quizá quieras sustituir los valores predeterminados por dos motivos:

  • Quizá quieras ajustar algunos de los parámetros de la escala predeterminada. Esto te permite, por ejemplo, cambiar las divisiones de los ejes o las etiquetas de las claves de la leyenda.

  • Quizá quieras reemplazar la escala por completo y usar un algoritmo totalmente distinto. A menudo puedes hacerlo mejor que el valor predeterminado porque sabes más sobre los datos.

Marcas de los ejes y claves de la leyenda

En conjunto, los ejes y las leyendas reciben en lets-plot el nombre, algo confuso, de guías (guides). Los ejes se usan para las estéticas x e y; las leyendas, para todo lo demás.

Hay dos argumentos principales que afectan al aspecto de las marcas de los ejes y de las claves de la leyenda: breaks y labels. breaks controla la posición de las marcas, o los valores asociados a las claves. Si quieres verlo así, los breaks son las marcas. labels controla la etiqueta de texto asociada a cada marca/clave. Sería más preciso llamarlas etiquetas de las marcas. El uso más común de breaks es sustituir la elección predeterminada:

(
    ggplot(mpg, aes(x="displ", y="hwy", color="drv"))
    + geom_point()
    + scale_y_continuous(breaks=np.arange(15, 40, step=5))
)

Puedes usar labels de la misma manera (es decir, pasando un array o una lista de strings de la misma longitud que breaks). Sin embargo, para eliminarlas por completo tendrías que usar un tema, un asunto al que volveremos más adelante. También puedes usar breaks y labels para controlar la apariencia de las leyendas. En las escalas discretas para variables categóricas, labels puede ser una lista con nombre de los niveles existentes y las etiquetas que quieres para ellos.

(
    ggplot(mpg, aes(x="displ", y="hwy", color="drv"))
    + geom_point()
    + scale_color_discrete(labels=["4-wheel", "front", "rear"])
)

Para cambiar el formato de las etiquetas de las marcas, usa el argumento de palabra clave format=. Esto es útil para mostrar monedas, porcentajes, etc., aunque a menudo es más fácil para el lector ver este símbolo una sola vez en la etiqueta del eje.

En el ejemplo siguiente, leemos el dataset diamonds y luego le damos formato con el comando format="$.2s"; desglosémoslo:

  • el signo de dólar indica que se ponga un signo de dólar delante de cada número
  • el .2 indica que se usen dos dígitos significativos
  • la s indica que se use el Sistema Internacional (SI)

Hay una gran variedad de opciones alternativas de formato; lo mejor es consultar la útil página sobre formatos de la documentación de lets-plot para saber más.

diamonds = pd.read_csv(
    "https://vincentarelbundock.github.io/Rdatasets/csv/ggplot2/diamonds.csv",
    index_col=0,
)
diamonds["cut"] = diamonds["cut"].astype(
    pd.CategoricalDtype(
        categories=["Fair", "Good", "Very Good", "Premium", "Ideal"], ordered=True
    )
)
diamonds["color"] = diamonds["color"].astype(
    pd.CategoricalDtype(categories=["D", "E", "F", "G", "H", "I", "J"], ordered=True)
)
(
    ggplot(diamonds, aes(x="cut", y="price"))
    + geom_boxplot()
    + coord_flip()
    + scale_y_continuous(format="$.2s", breaks=np.arange(0, 19000, step=6000))
)

Otro uso de breaks es cuando tienes relativamente pocos puntos de datos y quieres resaltar exactamente dónde se encuentran las observaciones. Por ejemplo, observa este gráfico que muestra cuándo comenzó y terminó su mandato cada presidente de EE. UU.

presidential = pd.read_csv(
    "https://vincentarelbundock.github.io/Rdatasets/csv/ggplot2/presidential.csv",
    index_col=0,
)
presidential = presidential.astype({"start": "datetime64[ns]", "end": "datetime64[ns]"})
presidential["id"] = 33 + presidential.index
presidential.head()
name start end party id
rownames
1 Eisenhower 1953-01-20 1961-01-20 Republican 34
2 Kennedy 1961-01-20 1963-11-22 Democratic 35
3 Johnson 1963-11-22 1969-01-20 Democratic 36
4 Nixon 1969-01-20 1974-08-09 Republican 37
5 Ford 1974-08-09 1977-01-20 Republican 38
(
    ggplot(presidential, aes(x="start", y="id"))
    + geom_point()
    + geom_segment(aes(xend="end", yend="id"))
    + scale_x_datetime()
)

Disposición de la leyenda

Lo más habitual es que uses breaks y labels para ajustar los ejes. Aunque ambos también funcionan con las leyendas, hay algunas otras técnicas que probablemente usarás más.

Para controlar la posición general de la leyenda, necesitas usar un ajuste de theme(). Volveremos a los temas al final del capítulo pero, en resumen, controlan las partes del gráfico que no son datos. El ajuste de tema legend.position controla dónde se dibuja la leyenda y, para demostrarlo, usaremos gggrid() para organizar todos los gráficos.

base = ggplot(mpg, aes(x="displ", y="hwy")) + geom_point(aes(color="class"))

p1 = base + theme(legend_position="right")  # the default
p2 = base + theme(legend_position="left")
p3 = base + theme(legend_position="top") + guides(color=guide_legend(nrow=3))
p4 = base + theme(legend_position="bottom") + guides(color=guide_legend(nrow=3))

gggrid([p1, p2, p3, p4], ncol=2)

Si tu gráfico es bajo y ancho, coloca la leyenda arriba o abajo; si es alto y estrecho, colócala a la izquierda o a la derecha. También puedes usar legend_position = "none" para suprimir por completo la visualización de la leyenda.

Para controlar la visualización de leyendas individuales, usa guides() junto con guide_legend() o guide_colorbar().

Reemplazar una escala

En lugar de solo ajustar un poco los detalles, puedes reemplazar la escala por completo. Hay dos tipos de escalas que probablemente querrás cambiar: las escalas de posición continuas y las escalas de color. Afortunadamente, los mismos principios se aplican a todas las demás estéticas, así que, una vez que domines la posición y el color, podrás aprender rápidamente otros reemplazos de escala.

Es muy útil graficar transformaciones de tu variable. Por ejemplo, es más fácil ver la relación precisa entre carat y price si les aplicamos una transformación logarítmica. La forma de hacerlo es usando una función apply() sobre los datos que se envían a ggplot:

(
    ggplot(
        diamonds.apply({"carat": np.log10, "price": np.log10}),
        aes(x="carat", y="price"),
    )
    + geom_bin2d()
)

Sin embargo, la desventaja de esta transformación es que ahora los ejes no están etiquetados con los valores originales, lo que dificulta interpretar el gráfico. En lugar de hacer la transformación en el mapeo estético, podemos hacerla con la escala. El resultado es visualmente idéntico, salvo que los ejes se etiquetan en la escala original de los datos.

(
    ggplot(diamonds, aes(x="carat", y="price"))
    + geom_bin2d()
    + scale_x_log10()
    + scale_y_log10()
)

Otra escala que se personaliza con frecuencia es el color. La escala categórica predeterminada elige colores espaciados uniformemente alrededor de la rueda de color. Unas alternativas útiles son las escalas ColorBrewer, que se han ajustado a mano para funcionar mejor con las personas que tienen tipos comunes de daltonismo. Los dos gráficos siguientes se ven parecidos, pero hay suficiente diferencia en los tonos de rojo y verde como para que los puntos de la derecha puedan distinguirse incluso por personas con daltonismo rojo-verde.

(ggplot(mpg, aes(x="displ", y="hwy")) + geom_point(aes(color="drv")))
(
    ggplot(mpg, aes(x="displ", y="hwy"))
    + geom_point(aes(color="drv"))
    + scale_color_brewer(palette="Set1")
)

No olvides técnicas más sencillas para mejorar la accesibilidad. Si solo hay unos pocos colores, puedes añadir un mapeo redundante de forma. Esto también ayudará a que tu gráfico se pueda interpretar en blanco y negro.

Las escalas ColorBrewer están documentadas en línea en https://colorbrewer2.org/. Las paletas secuenciales (arriba) y divergentes (abajo) son especialmente útiles si tus valores categóricos están ordenados o tienen un “centro”. Esto suele ocurrir si has usado pd.cut() para convertir una variable continua en una variable categórica.

# remove input
for cmap_category, cmap_list in cmaps[3:4]:
    plot_color_gradients(cmap_category, cmap_list)

# remove input
for cmap_category, cmap_list in cmaps[2:3]:
    plot_color_gradients(cmap_category, cmap_list)

Cuando tienes un mapeo predefinido entre valores y colores, usa scale_color_manual(). Por ejemplo, si mapeamos el partido presidencial al color, queremos usar el mapeo estándar de rojo para los republicanos y azul para los demócratas. Una forma de asignar estos colores es usar códigos de color hexadecimales:

mini_presid = presidential.iloc[5:, :]

(
    ggplot(mini_presid, aes(x="start", y="id", color="party"))
    + geom_point(size=3)
    + geom_segment(aes(xend="end", yend="id"), size=1)
    + scale_x_datetime(breaks=mini_presid["start"], format="%Y")
    + scale_color_manual(values=["#00AEF3", "#E81B23"], name="party")
)

También puedes usar nombres de colores típicos, como “red” y “blue”.

Para el color continuo, puedes usar las funciones integradas scale_color_gradient() o scale_fill_gradient(). Si tienes una escala divergente, puedes usar scale_color_gradient2(). Esto te permite, por ejemplo, dar colores diferentes a los valores positivos y negativos. A veces también es útil si quieres distinguir los puntos por encima o por debajo de la media.

Otra opción es usar las escalas de color viridis, magma, inferno y plasma desarrolladas para el potentísimo paquete imperativo de gráficos de Python matplotlib. Sus diseñadores, Nathaniel Smith y Stéfan van der Walt, crearon cuidadosamente esquemas de color continuos que son perceptibles para personas con diversas formas de daltonismo y perceptualmente uniformes tanto en color como en blanco y negro. Estas escalas están disponibles como paletas en lets-plot. Aquí tienes un ejemplo con la versión continua de viridis (primero generaremos algunos datos aleatorios):

prng = np.random.default_rng(1837)  # prng=probabilistic random number generator
df_rnd = pd.DataFrame(prng.standard_normal((1000, 2)), columns=["x", "y"])
(
    ggplot(df_rnd, aes(x="x", y="y"))
    + geom_bin2d()
    + coord_fixed()
    + scale_fill_viridis(option="plasma")
    + labs(title="Plasma, continua")
)

Zoom

Hay tres formas de controlar los límites del gráfico:

  1. Ajustar qué datos se grafican.
  2. Establecer los límites en cada escala.
  3. Establecer xlim y ylim en coord_cartesian().

Mostraremos estas opciones en una serie de gráficos. El primer gráfico muestra la relación entre el tamaño del motor y la eficiencia de combustible, coloreada por tipo de tracción. El segundo gráfico muestra las mismas variables, pero con un subconjunto de los datos graficados. Filtrar los datos ha afectado a las escalas x e y, así como a la curva suavizada.

(
    ggplot(mpg, aes(x="displ", y="hwy"))
    + geom_point(aes(color="drv"))
    + geom_smooth(method="loess")
)
mpg_condition = (
    (mpg["displ"] >= 5) & (mpg["displ"] <= 6) & (mpg["hwy"] >= 10) & (mpg["hwy"] <= 25)
)

(
    ggplot(mpg.loc[mpg_condition], aes(x="displ", y="hwy"))
    + geom_point(aes(color="drv"))
    + geom_smooth(method="loess")
)

Comparemos estos con los dos gráficos siguientes, donde el primero establece los limits en escalas individuales y el segundo los establece en coord_cartesian(). Podemos ver que reducir los límites equivale a filtrar los datos. Por lo tanto, para hacer zoom en una región del gráfico, generalmente es mejor usar coord_cartesian().

(
    ggplot(mpg, aes(x="displ", y="hwy"))
    + geom_point(aes(color="drv"))
    + geom_smooth(method="loess")
    + scale_x_continuous(limits=(5, 6))
    + scale_y_continuous(limits=(10, 25))
)
(
    ggplot(mpg, aes(x="displ", y="hwy"))
    + geom_point(aes(color="drv"))
    + geom_smooth(method="loess")
    + coord_cartesian(xlim=(5, 6), ylim=(10, 25))
)

Por otro lado, establecer los limits en escalas individuales suele ser más útil si quieres ampliar los límites, por ejemplo, para que las escalas coincidan entre distintos gráficos. Por ejemplo, si extraemos dos clases de autos y las graficamos por separado, es difícil comparar los gráficos porque las tres escalas (el eje x, el eje y y la estética de color) tienen rangos diferentes.

suv = mpg.loc[mpg["class"] == "suv"]
compact = mpg.loc[mpg["class"] == "compact"]
(ggplot(suv, aes(x="displ", y="hwy", color="drv")) + geom_point())
(ggplot(compact, aes(x="displ", y="hwy", color="drv")) + geom_point())

Una forma de resolver este problema es compartir las escalas entre varios gráficos, entrenando las escalas con los limits de los datos completos.

x_scale = scale_x_continuous(limits=mpg["displ"].agg(["max", "min"]).tolist())
y_scale = scale_y_continuous(limits=mpg["hwy"].agg(["max", "min"]).tolist())
col_scale = scale_color_discrete(limits=mpg["drv"].unique())
(
    ggplot(suv, aes(x="displ", y="hwy", color="drv"))
    + geom_point()
    + x_scale
    + y_scale
    + col_scale
)
(
    ggplot(compact, aes(x="displ", y="hwy", color="drv"))
    + geom_point()
    + x_scale
    + y_scale
    + col_scale
)

En este caso concreto podrías haber usado simplemente facetas, pero esta técnica es útil de forma más general, por ejemplo, si quieres repartir los gráficos en varias páginas de un informe.

Ejercicios

  1. ¿Cuál es el primer argumento de cada escala? ¿Cómo se compara con labs()?

  2. Cambia la visualización de los mandatos presidenciales:

    1. Combinando las dos variantes que personalizan los colores y los breaks del eje x.
    2. Mejorando la visualización del eje y.
    3. Etiquetando cada mandato con el nombre del presidente.
    4. Añadiendo etiquetas informativas al gráfico.
    5. Colocando breaks cada 4 años (¡es más complicado de lo que parece!).

Temas

Por último, puedes personalizar los elementos de tu gráfico que no son datos con un tema:

(
    ggplot(mpg, aes(x="displ", y="hwy"))
    + geom_point(aes(color="class"))
    + geom_smooth(se=False)
    + theme_grey()
)

lets-plot incluye varios temas integrados que puedes encontrar aquí. También puedes crear tus propios temas si quieres ajustarte a un estilo corporativo o de una revista concreta.

Aquí tienes un ejemplo en el que se cambian varios ajustes de theme():

(
    ggplot(mpg, aes(x="displ", color="drv"))
    + geom_density(size=2)
    + ggtitle("Densidad por tipo de tracción")
    + theme(
        axis_line=element_line(size=4),
        axis_ticks_length=10,
        axis_title_y="blank",
        legend_position=[1, 1],
        legend_justification=[1, 1],
        panel_background=element_rect(color="black", fill="#eeeeee", size=2),
        panel_grid=element_line(color="black", size=1),
    )
)

Ejercicios

  1. Haz que las etiquetas de los ejes de tu gráfico sean azules y estén en negrita.

Disposición

Hasta ahora hemos hablado de cómo crear y modificar un único gráfico. ¿Y si tienes varios gráficos que quieres disponer de cierta manera? Puedes hacerlo. Para colocar dos gráficos uno al lado del otro, basta con ponerlos en una lista y llamar a gggrid() sobre la lista. Ten en cuenta que primero debes crear los gráficos y guardarlos como objetos (en el siguiente ejemplo se llaman p1 y p2).

p1 = ggplot(mpg, aes(x="displ", y="hwy")) + geom_point() + labs(title="Gráfico 1")
p2 = ggplot(mpg, aes(x="drv", y="hwy")) + geom_boxplot() + labs(title="Gráfico 2")
gggrid([p1, p2])

Guardar gráficos en un archivo

Hay muchas opciones de salida entre las que elegir para guardar tu archivo. Recuerda que, para los gráficos, los formatos vectoriales suelen ser mejores que los formatos rasterizados. En la práctica, esto significa guardar los gráficos en formato svg o pdf en lugar de jpg o png. El formato svg funciona en muchos contextos (incluido Microsoft Word) y es una buena opción predeterminada. Para elegir entre formatos, solo tienes que indicar la extensión del archivo y el tipo cambiará automáticamente, por ejemplo, “chart.svg” para svg o “chart.png” para png (aunque ten en cuenta que los formatos rasterizados suelen tener opciones adicionales, como cuántos puntos por pulgada usar).

Probemos esto con la figura que hicimos en el ejercicio anterior, p1. path="." simplemente guarda el archivo en el directorio actual.

ggsave(p1, "chart.svg", path=".")
'/Users/jromero/personal/python4DS/es/chart.svg'

Para comprobar que ha funcionado, usemos la terminal. Probaremos el comando ls, que lista todo lo que hay en el directorio, y grep *.svg para extraer los archivos que terminan en .svg de lo que devuelve ls. Estos comandos se encadenan mediante un |. (Ten en cuenta que el signo de exclamación inicial que aparece abajo solo le indica al software que genera este libro que use la terminal).

!ls | grep *.svg
chart.svg

Resumen

En este capítulo has aprendido a añadir etiquetas a los gráficos, como el título, el subtítulo y la leyenda al pie, así como a modificar las etiquetas predeterminadas de los ejes, a usar anotaciones para añadir texto informativo a tu gráfico o para resaltar puntos de datos específicos, a personalizar las escalas de los ejes y a cambiar el tema de tu gráfico. También has aprendido a combinar varios gráficos en una sola figura usando disposiciones tanto simples como complejas.

Aunque hasta ahora has aprendido a crear muchos tipos de gráficos diferentes y a personalizarlos con diversas técnicas, apenas hemos rozado la superficie de lo que puedes crear con lets-plot.

El mejor lugar para obtener más información es la documentación de lets-plot.