La gramática de los gráficos
¿Por qué una “gramática” de los gráficos?
La mayoría de librerías de visualización exponen funciones tipo histogram(), barplot(), scatterplot(). Cada una con sus propios argumentos. ¿Quieres añadir una línea de tendencia a tu scatter? Aprende otra función. ¿Quieres facetar por categoría? Otra. La curva de aprendizaje es horizontal: cada gráfico nuevo es un esfuerzo nuevo.
En 1999, Leland Wilkinson publicó The Grammar of Graphics, una propuesta radical: en lugar de un catálogo de gráficos, un sistema gramatical de componentes que se combinan. Igual que combinas palabras en frases, combinas componentes en gráficos.
Hadley Wickham implementó esa idea en R como ggplot2. Eso es lo que hace que ggplot2 sea un lenguaje, no una librería de utilidades.
La consecuencia práctica: una vez aprendes los 7 componentes, cualquier gráfico que veas en una revista lo puedes reconstruir mentalmente. Y la mayoría los puedes escribir directamente.
Los 7 componentes de Wilkinson
Cualquier gráfico se descompone en estas capas:
| Capa | Qué define |
|---|---|
| Data | El dataset de entrada (data.frame o tibble) |
| Aesthetics | Cómo se mapean variables del dataset a propiedades visuales (x, y, color, size, shape…) |
| Geometries | Los objetos geométricos que aparecen (puntos, líneas, barras, polígonos) |
| Scales | Cómo se traducen los valores del dato a unidades visuales (rangos, transformaciones logarítmicas, paletas) |
| Facets | División del gráfico en sub-paneles (small multiples) |
| Coordinates | Sistema de coordenadas (cartesiano, polar, mapa) |
| Themes | Aspecto no relacionado con los datos (tipografía, fondo, leyendas) |
No todos los gráficos usan los siete. Casi todos usan los primeros tres (data + aesthetics + geometries). Los demás se añaden según necesidad.
Cómo se traducen a ggplot2
En código, esos siete componentes se mapean directamente:
library(ggplot2)
library(palmerpenguins) # install.packages("palmerpenguins") si no lo tienes
ggplot(data = penguins, # 1. Data
mapping = aes(x = bill_length_mm, # 2. Aesthetics
y = flipper_length_mm,
color = species)) +
geom_point(size = 2) + # 3. Geometry
scale_x_continuous(name = "Largo del pico (mm)") + # 4. Scale
facet_wrap(~ island) + # 5. Facet
coord_cartesian(xlim = c(30, 60)) + # 6. Coord
theme_minimal() # 7. ThemeLéelo: “sobre el dataset penguins, mapea el largo del pico al eje X y el de la aleta al eje Y coloreando por especie. Dibuja puntos. Pon una escala continua con un nombre legible en el eje X. Faceta por isla. Recorta el rango del eje X. Aplica el tema minimal”.
Cada línea es una capa que se suma a las anteriores. Por eso el operador entre componentes es +.
El + como suma de capas
Esta es la observación que separa entender ggplot2 de copiar código de StackOverflow.
ggplot(penguins, aes(bill_length_mm, flipper_length_mm)) +
geom_point()Aquí hay dos capas: una base (ggplot()) y un geom. Si quiero añadir una línea de tendencia, no cambio la función, añado otra capa:
ggplot(penguins, aes(bill_length_mm, flipper_length_mm)) +
geom_point() +
geom_smooth(method = "lm")¿Y si quiero el smooth solo para una especie?
ggplot(penguins, aes(bill_length_mm, flipper_length_mm)) +
geom_point() +
geom_smooth(data = dplyr::filter(penguins, species == "Adelie"),
method = "lm")Cada geom_*() puede tener su propio dataset y sus propios aesthetics, sobrescribiendo lo heredado del ggplot() base. Esa es la composicionalidad que la gramática habilita y que otras librerías no tienen.
Tu primer ggplot
Para que el resto de la ruta tenga base concreta, escribe esto:
library(ggplot2)
library(palmerpenguins)
ggplot(penguins, aes(x = bill_length_mm, y = flipper_length_mm)) +
geom_point(aes(color = species))Lo que has hecho:
- Has cargado
ggplot2y un dataset de ejemplo. - Has llamado
ggplot()con tres cosas: el data frame, el aestheticxy el aestheticy. - Has añadido una capa
geom_point()que dibuja un punto por fila del data frame, coloreado según la especie.
El resultado es un scatter plot con tres clusters claros, uno por especie. Ya tienes un EDA real con tres líneas de código.
Trampas habituales
- Olvidar el
+. Si terminas una línea sin+, la siguiente queda fuera del gráfico. R no avisa: simplemente la siguiente línea se ejecuta como código suelto. Diagnóstico: tu gráfico no muestra la capa que acabas de añadir. +al principio de la siguiente línea (en lugar de al final). ggplot2 acepta este estilo, pero es una fuente de errores cuando refactorizas: si borras una línea y olvidas el+huérfano, todo lo siguiente queda fuera. Convención sana:+siempre al final de la línea, nunca al principio.- Pensar en términos de funciones. Si te encuentras buscando “qué función dibuja un histograma con boxplot superpuesto”, estás pensando mal. Lo correcto es “añado un
geom_histogramy luego ungeom_boxplotcomo capas”. La gramática piensa en capas, no en figuras prefabricadas.
En la siguiente entrega
Tienes el modelo mental. La pieza más importante a fondo es el segundo componente, aesthetics (aes()). Es lo que mapea tus variables a propiedades visuales, y es el origen del 80 % de los errores que la gente comete en ggplot2. Lo vemos a continuación.