Visualizaciones con ggplot2
Universidad El Bosque
4 de junio de 2026
aes(): mapear variables vs. fijar valoreslabs()theme()facet_wrap() y facet_grid()ggsave()
En lugar de cargar cada paquete por separado — como library(ggplot2) y library(dplyr) — tidyverse los agrupa todos. Durante el curso irás conociendo varios.
Una sola línea carga 9 paquetes esenciales para el análisis de datos:
Parte 1
La gramática de las gráficas

ggplot2 implementa la Grammar of Graphics de Wilkinson: una figura se construye sumando capas independientes.
Cambiar cualquier capa deja las demás intactas. Eso hace que el código sea modular y fácil de modificar.
palmerpenguins contiene medidas de 344 pingüinos de tres especies en la Antártida.
Instala el paquete:
penguins tiene algunos valores faltantes (NA). Los eliminamos antes de graficar.
library(palmerpenguins)
# vamos a sobreescribir el objeto original para trabajar solo con los datos limpios
pinguinos <- penguins
pinguinos <- drop_na(penguins)
glimpse(pinguinos)Rows: 333
Columns: 8
$ species <fct> Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adel…
$ island <fct> Torgersen, Torgersen, Torgersen, Torgersen, Torgerse…
$ bill_length_mm <dbl> 39.1, 39.5, 40.3, 36.7, 39.3, 38.9, 39.2, 41.1, 38.6…
$ bill_depth_mm <dbl> 18.7, 17.4, 18.0, 19.3, 20.6, 17.8, 19.6, 17.6, 21.2…
$ flipper_length_mm <int> 181, 186, 195, 193, 190, 181, 195, 182, 191, 198, 18…
$ body_mass_g <int> 3750, 3800, 3250, 3450, 3650, 3625, 4675, 3200, 3800…
$ sex <fct> male, female, female, female, male, female, male, fe…
$ year <int> 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007…
Parte 2
Geometrías
Cada geom_*() pertenece a una de dos familias según cuántas variables necesita.
Una variable: ggplot2 calcula el resto
Solo defines x. La geometría resume los datos por ti.
x numérica: - geom_histogram(): distribución continua - geom_density(): curva de densidad suavizada
x categórica: - geom_bar(): contar por categoría
Dos variables: defines tanto x como y
y es siempre numérica. Lo que cambia es x:
x categórica → comparar grupos geom_boxplot(), geom_violin(), geom_jitter()
x numérica → ver relaciones geom_point(), geom_smooth(), geom_line()
Una variable · x numérica o categórica
Distribuciones y conteos
geom_histogram(): distribución continuax numérica. Divide los valores en intervalos y cuenta cuántas observaciones caen en cada uno.
bins fija el número de barras; binwidth fija el ancho de cada una. No uses ambos a la vez.
fill) y borde (colour); no todas las geometrías los tienen, pero sí las que encierran área (barras, cajas, violines)aes(), fijan un color igual para toda la geometría; dentro de aes() mapean los colores a una variable. Esto lo veremos en profundidad en la sección de estéticasgeom_density(): curva de densidadx numérica. Versión suavizada del histograma. Útil para comparar distribuciones entre grupos.
geom_bar(): conteos por categoríax categórica. Cuenta cuántas observaciones hay en cada grupo y dibuja una barra por categoría.
Añadimos fill = island en aes() para colorear las barras según una segunda variable:
position = "dodge" coloca las barras lado a lado; "stack" las apila (opción por defecto).
Dos variables · x + y
Relaciones y comparaciones
x categórica: comparar gruposCuando x es una variable categórica (especie, tratamiento, grupo…), las geometrías comparan la distribución de y entre esos grupos.
geom_violin() + geom_jitter()Combinar capas muestra la distribución completa y los datos individuales a la vez.
Las capas se dibujan en orden: el violín primero, los puntos encima. Cambia el orden y verás la diferencia.
x numérica: ver relacionesCuando x también es numérica, el objetivo es ver cómo varía y a medida que cambia x.
geom_smooth(): línea de tendenciaSe superpone sobre geom_point(). El argumento method define el tipo de ajuste.
method = "lm" ajusta una recta. method = "loess" ajusta una curva suave que sigue la tendencia en zonas de x. se = FALSE oculta el intervalo de confianza. Cámbialo por se = TRUE (o borra ese argumento) para mostrarlo.
geom_line(): series de tiempoConecta observaciones en orden de x. Apropiado cuando el orden importa.
economics es un conjunto de datos de ggplot2 con indicadores económicos de EE.UU.
Algunas sugerencias, pero ¡siempre puedes experimentar!
| Función | x | y | Cuándo usarla |
|---|---|---|---|
geom_histogram() |
📏 numérica | — | Distribución de una variable continua |
geom_density() |
📏 numérica | — | Como histogram, suavizado; útil para comparar grupos |
geom_bar() |
📶 categórica | — | Contar observaciones por categoría |
geom_boxplot() |
📶 categórica | 📏 numérica | Comparar distribuciones entre grupos (mediana y rango) |
geom_violin() |
📶 categórica | 📏 numérica | Como boxplot, muestra la forma completa de la distribución |
geom_jitter() |
📶 categórica | 📏 numérica | Puntos individuales, evita solapamiento |
geom_point() |
📏 numérica | 📏 numérica | Relación entre dos variables numéricas (dispersión) |
geom_smooth() |
📏 numérica | 📏 numérica | Línea de tendencia sobre un diagrama de puntos |
geom_line() |
📆 tiempo / orden | 📏 numérica | Series de tiempo o datos ordenados |
ggplot2 tiene muchísimas geometrías más para distintos propósitos: mapas, gráficos de red, etc. Consulta la documentación oficial para verlas.
Actividad · 10 min
Tres figuras, tres geometrías
Con el dataset pinguinos, crea una figura de cada tipo:
x)x categórica + y numérica)x y y numéricas)Añade theme_minimal() y un título con labs().
Parte 3
aes(): mapear vs. fijar
aes(): variable → estéticaCuando una estética depende de los datos, va dentro de aes().
Cada especie recibe un color distinto según los datos.
aes(): valor fijo para todosCuando la estética es un valor constante, va fuera de aes(), directamente en el geom_*().
Todos los puntos tienen el mismo color, tamaño y transparencia.
aes()aes()Se pueden mapear varias variables a distintas estéticas simultáneamente.
Mapear colour y shape a la misma variable mejora la accesibilidad: la figura es legible incluso en escala de grises.
Actividad · 3 min
El reto del color rojo
Crea un scatterplot de bill_length_mm vs body_mass_g en pinguinos donde todos los puntos sean rojos.
Parte 4
Etiquetas con labs()
labs(): títulos y etiquetaslabs() controla todos los textos de la figura: título, subtítulo, ejes, leyenda y nota al pie.
ggplot(
pinguinos,
aes(
x = bill_length_mm,
y = body_mass_g,
colour = species
)
) +
geom_point(alpha = 0.7) +
scale_colour_viridis_d() +
labs(
title = "Masa corporal y longitud del pico",
subtitle = "Pingüinos de Palmer, Antártida",
x = "Longitud del pico (mm)",
y = "Masa corporal (g)",
colour = "Especie",
caption = "Datos: Horst, Hill & Gorman (2020)"
) +
theme_minimal()Parte 5
Temas y personalización
ggplot2 incluye varios temas listos para usar.
Aplícalos sumándolos a la figura:
theme()theme() permite ajustar cualquier elemento visual de la figura.
element_blank() elimina un elemento. element_text() controla fuente, tamaño y color. element_line() y element_rect() hacen lo propio con líneas y rectángulos.
Parte 6
Paletas de colores
scale_colour_*() y scale_fill_*()Las funciones scale_*() controlan cómo se mapean los datos a las estéticas visuales.
# Viridis: perceptualmente uniforme, apto para daltonismo
scale_colour_viridis_d() # variable discreta
scale_colour_viridis_c() # variable continua
scale_colour_viridis_d(option = "plasma") # variante: magma, plasma, inferno, cividis
# ColorBrewer: paletas curadas para cartografía y visualización
scale_colour_brewer(palette = "Set2") # discreta
scale_fill_brewer(palette = "Blues") # continua
# Manual: colores definidos a mano
scale_colour_manual(values = c("#121834", "#225faa", "#ddeaf8"))Usa scale_colour_*() para estéticas colour= y scale_fill_*() para fill=. Algunas geoms tienen borde (colour) y relleno (fill); otras solo usan colour.
HEX es un formato de color que combina rojo, verde y azul en un código de 6 dígitos (precedido por #). Por ejemplo, #225faa es un azul específico. En Google busca “selector de color” para obtener el código HEX de cualquier color.
Parte 7
Facetas
facet_wrap(): un panel por categoríaDivide la figura en paneles según los valores de una variable.
facet_grid(): dos variables, filas y columnasOrganiza los paneles en una cuadrícula con una variable por eje.
La sintaxis filas ~ columnas define qué variable va en cada dimensión.
Parte 8
Guardar figuras
ggsave()Guarda la última figura generada (o la que especifiques) en el formato que elijas.
mi_figura <- ggplot(
pinguinos,
aes(x = bill_length_mm, y = body_mass_g,
colour = species, shape = species)
) +
geom_point(alpha = 0.7, size = 2) +
scale_colour_viridis_d() +
theme_minimal()
# PNG para presentaciones y web
ggsave("pinguinos.png",
plot = mi_figura,
width = 16, height = 10,
units = "cm", dpi = 300
)
# PDF para publicaciones (vectorial, escala sin pérdida)
ggsave("pinguinos.pdf",
plot = mi_figura,
width = 16, height = 10,
units = "cm"
)dpi = 300 es el estándar para publicación impresa. Para pantalla, dpi = 150 es suficiente. units = "cm" permite especificar el tamaño exacto que pedirá la revista.
Por ahora la figura se guarda en la misma carpeta donde está tu script (o en Documentos si no has guardado el script aún). En la Sesión 4 crearás un proyecto organizado con una estructura más clara.
Todo lo visto en una sola figura.
ggplot(pinguinos,
aes(x = bill_length_mm,
y = body_mass_g,
colour = species,
shape = species)) +
geom_point(alpha = 0.6, size = 2) +
geom_smooth(method = "lm",
se = FALSE,
linewidth = 0.8) +
facet_wrap(~island) +
scale_colour_brewer(name = "Especie",
palette = "Dark2") +
scale_shape_discrete(name = "Especie") +
labs(title = "Masa y pico por isla",
x = "Longitud del pico (mm)",
y = "Masa corporal (g)",
caption = "Datos: Horst et al. (2020)") +
theme_linedraw() +
theme(legend.position = "bottom")Antes de terminar…
Quiz rápido
¿De qué color quedan los puntos con este código?
"blue" como coloraes() no se puede fijar un color✓ b) aes(colour = "blue") crea una categoría llamada "blue" y le asigna el primer color de la paleta por defecto. Para fijar azul de verdad: geom_point(colour = "blue"), fuera de aes().
¿Qué función de escala Viridis completaría correctamente esta figura?
scale_colour_viridis_c(): island es categórica, pero el mapping es colourscale_fill_viridis_c(): el mapping es colour, pero island no es continuascale_colour_viridis_d(): el mapping es colour e island es categóricascale_fill_viridis_b(): _b es para variables continuas en intervalos✓ c) Dos reglas: la función debe coincidir con la estética (colour → scale_colour_*), y el sufijo con el tipo de variable (island es categórica → _d).
¿Cuál es la diferencia principal entre geom_boxplot() y geom_violin()?
geom_boxplot() muestra mediana y cuartiles; geom_violin() muestra la forma completa de la distribucióngeom_violin() es para variables continuas; geom_boxplot() para categóricasgeom_boxplot() necesita x e y; geom_violin() solo necesita x✓ b) El boxplot resume la distribución en cinco números. El violín muestra toda la forma (incluyendo si hay uno o dos picos, colas, etc. Por eso se combinan bien).
¿Qué produce facet_wrap(~species) en una figura de pinguinos?
✓ c) facet_wrap() divide la figura en paneles, uno por cada valor único de la variable indicada. Con ~species y tres especies, obtienes tres paneles con la misma escala.
¿Para qué sirve labs() en una figura de ggplot2?
✓ d) labs() gestiona todos los textos de la figura. Sin labs(), los ejes muestran el nombre de la variable tal como está en la base de datos y no hay título.
Antes de la próxima sesión, usa el dataset gapminder para crear una figura que explore la relación entre esperanza de vida y PIB per cápita.
Experimenta con:
colour = continent)facet_wrap(~year)) o filtra un año concretoscale_x_log10()labs() con título, ejes y fuenteggsave() para guardar el resultadoHasta la próxima sesión
¡Gracias!
Curso de R · Universidad El Bosque · Junio 2026 · ↩︎ Sitio del curso