Visualización Multiple
Visualizando múltiples dimensiones simultáneamente
Hasta ahora hemos trabajado principalmente con dos dimensiones: una variable en el eje X y otra en el eje Y. Sin embargo, Observable Plot permite codificar información adicional usando otros canales visuales (Mackinlay, 1986):
- Tamaño de los elementos (puntos, barras)
- Color para categorías o valores continuos
- Opacidad para densidad o magnitud
- Texto para etiquetar elementos específicos
- Forma para diferentes grupos
En esta lección aprenderemos a:
- Usar tamaño variable (
r) para representar una tercera variable - Aplicar color por categoría (
fillcomo variable) - Controlar opacidad (
fillOpacitycon datos) - Agregar etiquetas de texto (
Plot.text()) - Combinar múltiples marcas en un mismo gráfico
- Trabajar con leyendas automáticas
Gráfico base
Comenzaremos con un scatter plot que relaciona PIB y expectativa de vida:
Ver código Plot.plot gráfico base
Plot.plot({
width: 900,
height: 550,
marginLeft: 80,
title: "Relación entre PIB y expectativa de vida",
subtitle: "Datos de 195 países (2023)",
caption: "Fuente: World Data 2023 (Kaggle)",
x: {
label: "PIB (billones de USD)",
grid: true,
tickFormat: (d) => `$${(d / 1e9).toFixed(0)}B`,
type: "log",
},
y: {
label: "Expectativa de vida (años)",
grid: true,
},
marks: [
Plot.dot(datos, {
x: "gdp_usd",
y: "life_expectancy",
fill: "steelblue",
fillOpacity: 0.6,
stroke: "darkblue",
strokeWidth: 1.5,
}),
],
})
Este gráfico muestra dos variables, pero cada punto es idéntico en tamaño. No podemos saber, por ejemplo, si un país tiene mucha o poca población.
Agregando una tercera variable con tamaño: r
La propiedad r (radio) permite variar el tamaño de los puntos según una tercera variable.
Ver código Plot.plot con r variable
Plot.plot({
width: 900,
height: 550,
marginLeft: 80,
title: "PIB, expectativa de vida y población mundial",
subtitle: "Datos de 195 países (2023) • El tamaño representa la población",
caption: "Fuente: World Data 2023 (Kaggle)",
x: {
label: "PIB (billones de USD)",
grid: true,
tickFormat: (d) => `$${(d / 1e9).toFixed(0)}B`,
type: "log",
},
y: {
label: "Expectativa de vida (años)",
grid: true,
},
marks: [
Plot.dot(datos, {
x: "gdp_usd",
y: "life_expectancy",
r: "population",
fill: "steelblue",
fillOpacity: 0.6,
stroke: "darkblue",
strokeWidth: 1.5,
}),
],
})
¿Qué cambió?
Se agregó:
- r: "population": el radio de cada punto ahora representa la población del país
Los puntos más grandes representan países con mayor población (como China e India), mientras que los pequeños representan países con poblaciones menores.
Controlando el rango de tamaños
Por defecto, Plot escala automáticamente los tamaños, pero podemos controlarlo con la configuración del canal r:
Ver código Plot.plot con rango de tamaños
Plot.plot({
width: 900,
height: 550,
marginLeft: 80,
title: "PIB, expectativa de vida y población mundial",
subtitle:
"Datos de 195 países (2023) • Tamaños ajustados para mejor visualización",
caption: "Fuente: World Data 2023 (Kaggle)",
x: {
label: "PIB (billones en USD)",
grid: true,
tickFormat: (d) => `$${(d / 1e9).toFixed(0)}B`,
type: "log",
},
y: {
label: "Expectativa de vida (años)",
grid: true,
},
r: {
range: [2, 20],
},
marks: [
Plot.dot(datos, {
x: "gdp_usd",
y: "life_expectancy",
r: "population",
fill: "steelblue",
fillOpacity: 0.6,
stroke: "darkblue",
strokeWidth: 1.5,
}),
],
})
¿Qué cambió?
Se agregó:
- r: { range: [2, 20] }: define que el radio mínimo será 2px y el máximo 20px
Esto evita que los puntos sean demasiado pequeños (invisibles) o demasiado grandes (superpuestos).
Guía para rangos de tamaño
Puntos pequeños ([1, 10]):
- Cuando hay muchos datos superpuestos
- Gráficos pequeños
- Diferencias sutiles de tamaño
Puntos medianos ([2, 20]):
- Recomendado para la mayoría de casos
- Balance entre visibilidad y superposición
- Gráficos de tamaño estándar
Puntos grandes ([5, 40]):
- Pocos puntos
- Cuando se quiere enfatizar diferencias
- Visualizaciones principales o pósters
Agregando color por categoría
Hasta ahora todos los puntos tienen el mismo color. Podemos usar fill como variable para colorear según categorías.
Primero, necesitamos crear una categorización. Agruparemos países por nivel de desarrollo basado en PIB:
Ver preparación de datos
const datosConCategoria = datos.map((d) => ({
...d,
development_level:
d.gdp_usd < 100e9
? "Bajo PIB"
: d.gdp_usd < 1000e9
? "PIB Medio"
: "PIB Alto",
}))
¿Qué hace cada parte?
datos.map(d => ...)
- map() recorre cada elemento (país) del array de datos
- d representa cada país individual
- Transforma cada elemento y devuelve un nuevo array
{ ...d, ... }
...d(spread operator) copia todas las propiedades existentes del país- Esto preserva todas las variables originales: gdp_usd, population, life_expectancy, etc.
- Sin esto, perderíamos todas las columnas originales
"development_level": ...
- Agrega una nueva propiedad llamada "development_level"
- Esta nueva columna se suma a las existentes
d.gdp_usd < 100e9 ? "Bajo PIB" : ...
- Operador (condición ? valor_si_verdadero : valor_si_falso)
- 100e9 = 100,000,000,000 (100 billones en USD)
- Si el PIB es menor a 100 mil millones → "Bajo PIB"
d.gdp_usd < 1000e9 ? "PIB Medio" : ...
- Operador (condición ? valor_si_verdadero : valor_si_falso)
- 1000e9 = 1,000,000,000,000 (1 trillón en USD)
- Si el PIB es menor a 1 billón → "PIB Medio"
Ver código Plot.plot con color categórico
Plot.plot({
width: 900,
height: 550,
marginLeft: 80,
title: "PIB, expectativa de vida y población por nivel de desarrollo",
subtitle: "Datos de 195 países (2023) • Coloreado por nivel de PIB",
caption: "Fuente: World Data 2023 (Kaggle)",
x: {
label: "PIB (billones en USD)",
grid: true,
tickFormat: (d) => `$${(d / 1e9).toFixed(0)}B`,
type: "log",
},
y: {
label: "Expectativa de vida (años)",
grid: true,
},
r: {
range: [2, 20],
},
color: {
legend: true,
},
marks: [
Plot.dot(datosConCategoria, {
x: "gdp_usd",
y: "life_expectancy",
r: "population",
fill: "development_level",
fillOpacity: 0.7,
stroke: "white",
strokeWidth: 1,
}),
],
})
¿Qué cambió?
Se agregó:
- datosConCategoria: creamos una nueva variable categórica "development_level"
- fill: "development_level": el color ahora varía según esta categoría
- color: { legend: true }: activa la leyenda automática de colores
Ahora podemos ver patrones: los países de PIB Alto (azul) tienden a tener mayor expectativa de vida.
Paletas de colores para categorías
Observable Plot usa paletas predefinidas, pero podemos personalizarlas:
Ver código Plot.plot con paleta personalizada
Plot.plot({
width: 900,
height: 550,
marginLeft: 80,
title: "PIB, expectativa de vida y población por nivel de desarrollo",
subtitle: "Datos de 195 países (2023) • Paleta personalizada",
caption: "Fuente: World Data 2023 (Kaggle)",
x: {
label: "PIB (billones de USD)",
grid: true,
tickFormat: (d) => `$${(d / 1e9).toFixed(0)}B`,
type: "log",
},
y: {
label: "Expectativa de vida (años)",
grid: true,
},
r: {
range: [2, 20],
},
color: {
domain: ["Bajo PIB", "PIB Medio", "PIB Alto"],
range: ["#ef4444", "#f59e0b", "#10b981"],
legend: true,
},
marks: [
Plot.dot(datosConCategoria, {
x: "gdp_usd",
y: "life_expectancy",
r: "population",
fill: "development_level",
fillOpacity: 0.7,
stroke: "white",
strokeWidth: 1,
}),
],
})
¿Qué cambió?
Se agregó en la configuración de color:
- domain: define el orden de las categorías
- range: define los colores específicos para cada categoría
Colores usados:
- #ef4444 (rojo) para Bajo PIB
- #f59e0b (naranja) para PIB Medio
- #10b981 (verde) para PIB Alto
Mejores prácticas para color categórico
Número de categorías: (Brewer, 2023), (Ware, 2021)
- 2-3 categorías: cualquier paleta funciona
- 4-6 categorías: usar paletas diseñadas (ColorBrewer, Tableau)
- 7+ categorías: difícil de distinguir, considerar agrupar
Accesibilidad: (Okabe, 2008), (Wong, 2011)
- Evitar rojo-verde para daltonismo
- Usar suficiente contraste entre categorías
- Considerar patrones además de color
Paletas recomendadas:
Ver código paletas recomendadas
// Paleta amigable con daltonismo
range: ["#0173B2", "#DE8F05", "#029E73", "#CC78BC"]
// Paleta neutral
range: ["#4B5563", "#9CA3AF", "#D1D5DB", "#F3F4F6"]
// Paleta cálida a fría
range: ["#DC2626", "#F59E0B", "#10B981", "#3B82F6"]
Color con variable continua
Además de categorías, podemos usar color para representar una variable numérica continua:
Ver código Plot.plot con color continuo
Plot.plot({
width: 900,
height: 550,
marginLeft: 80,
title: "PIB, expectativa de vida, población y emisiones de CO₂",
subtitle: "Datos de 195 países (2023) • Color representa emisiones de CO₂",
caption: "Fuente: World Data 2023 (Kaggle)",
x: {
label: "PIB (billones de USD)",
grid: true,
tickFormat: (d) => `$${(d / 1e9).toFixed(0)}B`,
type: "log",
},
y: {
label: "Expectativa de vida (años)",
grid: true,
},
r: {
range: [2, 20],
},
color: {
type: "linear",
scheme: "YlOrRd",
legend: true,
label: "Emisiones CO₂ en millones",
domain: [0, 10],
},
marks: [
Plot.dot(datos, {
x: "gdp_usd",
y: "life_expectancy",
r: "population",
fill: "co2_emissions_kt",
fillOpacity: 0.8,
stroke: "white",
strokeWidth: 1,
}),
],
})
¿Qué cambió?
Se agregó:
- fill: "co2_emissions_kt": color basado en variable numérica continua
- color: { type: "linear" }: escala lineal de colores
- scheme: "YlOrRd": esquema de amarillo a naranja a rojo
Ahora estamos visualizando CINCO variables simultáneamente:
- Eje X: PIB
- Eje Y: Expectativa de vida
- Tamaño: Población
- Color: Emisiones de CO₂
- Posición: Cada punto es un país
Esquemas de color para variables continuas
Secuenciales (un color):
- Blues: para una sola variable positiva
- Greens: alternativa verde
- Reds: para alertas o negativos
Divergentes (dos colores):
- RdBu: rojo-azul, para valores positivos/negativos
- PiYG: rosa-verde, alternativa divergente
- BrBG: café-verde
Multi-hue (varios colores):
- YlOrRd: amarillo-naranja-rojo, para intensidad
- Viridis: paleta perceptualmente uniforme (van der Walt, 2015)
- Turbo: amplio rango de colores
Ver código esquemas de color
// Ejemplos de uso:
color: {
scheme: "Blues"
} // Azules secuenciales
color: {
scheme: "RdBu"
} // Rojo-azul divergente
color: {
scheme: "Viridis"
} // Viridis (científico)
color: {
scheme: "YlOrRd"
} // Amarillo-rojo (calor)
Agregando etiquetas de texto
Para identificar países específicos, podemos agregar etiquetas usando Plot.text():
Ver preparación de datos
const paisesDestacados = datos.filter((d) => d.population > 100e6)
Ver código Plot.plot con etiquetas de países
Plot.plot({
width: 900,
height: 550,
marginLeft: 80,
title: "PIB y expectativa de vida con países más poblados etiquetados",
subtitle:
"Datos de 195 países (2023) • Etiquetados países con más de 100 millones de habitantes",
caption: "Fuente: World Data 2023 (Kaggle)",
x: {
label: "PIB (billones de USD)",
grid: true,
tickFormat: (d) => `$${(d / 1e9).toFixed(0)}B`,
type: "log",
},
y: {
label: "Expectativa de vida (años)",
grid: true,
},
r: {
range: [2, 20],
},
marks: [
// Puntos de todos los países
Plot.dot(datos, {
x: "gdp_usd",
y: "life_expectancy",
r: "population",
fill: "steelblue",
fillOpacity: 0.5,
stroke: "darkblue",
strokeWidth: 1,
}),
// Etiquetas solo de países destacados
Plot.text(paisesDestacados, {
x: "gdp_usd",
y: "life_expectancy",
text: "country",
fontSize: 12,
fontWeight: "bold",
dy: -8,
}),
],
})
¿Qué cambió?
Se agregaron dos marcas diferentes:
- Plot.dot(): todos los puntos
- Plot.text(): etiquetas solo para países con más de 100M habitantes
Propiedades de Plot.text():
- text: "country": qué variable usar como texto
- fontSize: 11: tamaño de la letra
- fontWeight: "bold": letra bold (negritas)
- dy: -8: desplazamiento vertical (negativo = arriba)
Propiedades útiles para texto
Posicionamiento:
Ver código Plot.text posicionamiento
Plot.text(datos, {
x: "variable_x",
y: "variable_y",
text: "nombre",
dx: 10, // Desplazamiento horizontal
dy: -10, // Desplazamiento vertical
textAnchor: "start", // "start", "middle", "end"
})
Estilo:
Ver código Plot.text estilo
Plot.text(datos, {
text: "nombre",
fontSize: 12,
fontWeight: "bold",
fill: "black",
stroke: "white", // Contorno blanco
strokeWidth: 3,
})
Rotación:
Ver código Plot.text rotación
Plot.text(datos, {
text: "nombre",
rotate: 45, // Grados de rotación
})
Agregando etiquetas en barras
Las etiquetas son muy útiles en gráficos de barras para mostrar los valores exactos:
Ver preparación de datos
const top10 = datos
.filter((d) => d["life_expectancy"] != null)
.sort((a, b) => b["life_expectancy"] - a["life_expectancy"])
.slice(0, 10)
Ver código Plot.plot barras con etiquetas
Plot.plot({
width: 900,
height: 400,
marginLeft: 150,
title: "Top 10 países con mayor expectativa de vida",
subtitle: "Año 2023 • Con valores exactos",
caption: "Fuente: World Data 2023 (Kaggle)",
x: {
label: "Expectativa de vida (años)",
grid: true,
domain: [75, 90],
clamp: true,
},
y: {
label: null,
},
marks: [
// Barras
Plot.barX(top10, {
y: "country",
x: "life_expectancy",
fill: "forestgreen",
fillOpacity: 0.8,
stroke: "darkgreen",
strokeWidth: 1,
}),
// Etiquetas con valores
Plot.text(top10, {
y: "country",
x: "life_expectancy",
text: (d) => d["life_expectancy"].toFixed(1),
textAnchor: "start",
dx: 5,
fill: "black",
fontSize: 11,
fontWeight: "bold",
}),
],
})
¿Qué cambió?
Se combinaron dos marcas:
- Plot.barX(): las barras
- Plot.text(): etiquetas con los valores
- textAnchor: "start": alinea el texto por fuera de la barra
- dx: 5: desplaza el texto 5px a la derecha de la barra
- text: d => d["life_expectancy"].toFixed(1): formatea el valor a 1 decimal
Nota importante: textAnchor: utiliza también "end", "center", "middle", ...
Combinando múltiples marcas: líneas de referencia
Podemos agregar líneas de referencia para mostrar promedios o umbrales:
Ver preparación de datos
const promedioVida = d3.mean(datos, (d) => d["life_expectancy"])
Obtenemos el promedio de la expectativa de vida.
Ver código Plot.plot con línea de referencia
Plot.plot({
width: 900,
height: 550,
marginLeft: 80,
title: "PIB vs expectativa de vida con promedio mundial",
subtitle: `Datos de 195 países (2023) • Promedio mundial: ${promedioVida.toFixed(
1
)} años`,
caption: "Fuente: World Data 2023 (Kaggle)",
x: {
label: "PIB (billones de USD)",
grid: true,
tickFormat: (d) => `$${(d / 1e9).toFixed(0)}B`,
type: "log",
},
y: {
label: "Expectativa de vida (años)",
grid: true,
},
r: {
range: [2, 20],
},
marks: [
// Puntos
Plot.dot(datos, {
x: "gdp_usd",
y: "life_expectancy",
r: "population",
fill: "steelblue",
fillOpacity: 0.6,
stroke: "darkblue",
strokeWidth: 1,
}),
// Línea horizontal del promedio
Plot.ruleY([promedioVida], {
stroke: "red",
strokeWidth: 2,
strokeDasharray: "5,5",
}),
// Etiqueta del promedio
Plot.text(
[{ y: promedioVida, label: `Promedio: ${promedioVida.toFixed(1)} años` }],
{
x: 2e12,
y: "y",
text: "label",
textAnchor: "end",
fill: "red",
fontWeight: "bold",
dy: -5,
}
),
],
})
¿Qué cambió?
Se agregaron tres marcas:
- Plot.dot(): los puntos de datos
- Plot.ruleY(): línea horizontal en el promedio
- Plot.text(): etiqueta explicativa
Propiedades de Plot.ruleY():
- strokeDasharray: "5,5": línea punteada (5px línea, 5px espacio)
- stroke: "red": color rojo para destacar
- strokeWidth: 2: grosor de 2px
Gráfico completo: 5 dimensiones
Veamos un gráfico que combina todo lo aprendido:
Ver preparación de datos
const datosConRegion = datos.map((d) => ({
...d,
Región: d.continent || "Others",
}))
const paisesGrandes = datosConRegion.filter((d) => d.population > 200e6)
const promedioGlobal = d3.mean(datos, (d) => d["life_expectancy"])
Este código toma directamente el valor de la columna continent y crea la nueva propiedad Región. El operador || "Others" maneja el caso de que algún país no tenga definido su continente.
Ver código Plot.plot gráfico completo 5 dimensiones
Plot.plot({
width: 1000,
height: 600,
marginLeft: 80,
marginRight: 150,
title: "Panorama global: PIB, expectativa de vida, población y región",
subtitle:
"Datos de 195 países (2023) • Tamaño = población, Color = región geográfica",
caption:
"Fuente: World Data 2023 (Kaggle) | Etiquetados países con más de 200M de habitantes",
style: {
fontSize: "13px",
},
x: {
label: "PIB (billones de USD)",
grid: true,
type: "log",
tickFormat: (d) => `$${(d / 1e9).toFixed(0)}B`,
domain: [1e8, 100e12],
},
y: {
label: "Expectativa de vida (años)",
grid: true,
domain: [50, 90],
},
r: {
range: [2, 30],
},
color: {
domain: [
"North America",
"Central America",
"South America",
"Europe",
"Africa",
"Asia",
"Oceania",
"Others",
],
range: [
"#2563EB", // América del Norte (azul fuerte)
"#06B6D4", // América Central (cian)
"#10B981", // América del Sur (verde)
"#8B5CF6", // Europa (violeta)
"#F43F5E", // África (rojo)
"#F59E0B", // Asia (ámbar)
"#22C55E", // Oceanía (verde claro)
"#9CA3AF", // Otros (gris neutro)
],
legend: true,
},
marks: [
// Línea de promedio
Plot.ruleY([promedioGlobal], {
stroke: "#EF4444",
strokeWidth: 2,
strokeDasharray: "4,4",
}),
// Puntos principales
Plot.dot(datosConRegion, {
x: "gdp_usd",
y: "life_expectancy",
r: "population",
fill: "Región",
fillOpacity: 0.7,
stroke: "gray",
strokeWidth: 1.5,
}),
// Etiquetas de países grandes
Plot.text(paisesGrandes, {
x: "gdp_usd",
y: "life_expectancy",
text: "country",
fontSize: 10,
fontWeight: "bold",
fill: "blue",
dy: -8,
stroke: "white",
strokeWidth: 2,
}),
// Etiqueta del promedio
Plot.text(
[
{
x: 1e11,
y: promedioGlobal,
label: `Promedio mundial: ${promedioGlobal.toFixed(1)} años`,
},
],
{
x: "x",
y: "y",
text: "label",
textAnchor: "start",
fill: "#EF4444",
fontWeight: "bold",
fontSize: 11,
dy: -8,
}
),
],
})
Este gráfico muestra:
- 5 variables: PIB (X), Expectativa de vida (Y), Población (tamaño), Región (color), País (texto)
- Escala logarítmica en X para mejor distribución
- Línea de referencia del promedio mundial
- Etiquetas de países más poblados
- Leyenda automática de colores
- Contexto completo (título, subtítulo, caption)
Leyendas personalizadas
Las leyendas se generan automáticamente cuando usamos fill o r con variables, pero podemos personalizarlas:
Ver código Plot.plot con leyenda personalizada
Plot.plot({
width: 900,
height: 550,
title: "PIB vs expectativa de vida por nivel de desarrollo",
x: {
label: "PIB (billones de USD)",
tickFormat: (d) => `$${(d / 1e9).toFixed(0)}B`,
type: "log",
},
y: {
label: "Expectativa de vida (años)",
},
color: {
domain: ["Bajo PIB", "PIB Medio", "PIB Alto"],
range: ["#EF4444", "#F59E0B", "#10B981"],
legend: true,
label: "Clasificación económica",
},
marks: [
Plot.dot(datosConCategoria, {
x: "gdp_usd",
y: "life_expectancy",
fill: "development_level",
fillOpacity: 0.7,
}),
],
})
Propiedades de leyenda:
- legend: true: activa la leyenda
- label: título de la leyenda
- domain: orden de categorías
- range: colores específicos
Aplicando a histogramas
Las técnicas de codificación múltiple también funcionan en otros tipos de gráficos:
Ver código Plot.plot histograma con color por categoría
Plot.plot({
width: 900,
height: 450,
marginTop: 50,
title: "Distribución de expectativa de vida por nivel de desarrollo",
subtitle: "Datos de 195 países (2023)",
caption: "Fuente: World Data 2023 (Kaggle)",
x: {
label: "Expectativa de vida (años)",
grid: true,
},
y: {
label: "Número de países",
grid: true,
},
color: {
domain: ["Bajo PIB", "PIB Medio", "PIB Alto"],
range: ["#EF4444", "#F59E0B", "#10B981"],
legend: true,
},
marks: [
Plot.rectY(
datosConCategoria,
Plot.binX(
{ y: "count" },
{
x: "life_expectancy",
fill: "development_level",
fillOpacity: 0.7,
stroke: "white",
strokeWidth: 2,
}
)
),
],
})
Ahora el histograma está segmentado por color según el nivel de desarrollo económico.
Resumen de propiedades
| Propiedad | Canal visual | Tipo de variable | Uso principal |
|---|---|---|---|
| r | Tamaño | Numérica continua | Magnitud, población, importancia |
| fill (variable categórica) | Color | Categórica | Grupos, regiones, tipos |
| fill (variable continua) | Color | Numérica continua | Intensidad, temperatura, densidad |
| fillOpacity | Opacidad | Numérica continua | Densidad, confianza, énfasis |
| text | Texto | Cualquiera | Identificación, valores exactos |
Conclusiones de la lección
En esta lección se ha explorado cómo usar múltiples canales visuales simultáneamente para representar más dimensiones de información en un solo gráfico.
Conceptos clave
Canales visuales múltiples
- r (tamaño) permite agregar una tercera variable numérica
- fill puede usarse tanto para categorías como para variables continuas
- Plot.text() permite etiquetar elementos específicos
- Se pueden combinar múltiples marcas (puntos + texto + líneas)
Leyendas automáticas
- Se generan automáticamente cuando fill o r usan variables
- Se pueden personalizar con color: { legend: true, label: "..." }
- El orden y colores se controlan con domain y range
Buenas prácticas
- No saturar: 4-5 variables es el máximo recomendado
- Usar color con propósito: para categorías importantes o gradientes significativos
- Etiquetar selectivamente: solo elementos destacados o outliers
- Mantener legibilidad: ajustar opacidades y tamaños apropiadamente
Reflexión final
La codificación visual múltiple es una herramienta poderosa que permite contar historias complejas en un solo gráfico (Munzner, 2015). Sin embargo, con gran poder viene gran responsabilidad:
- Más no siempre es mejor: un gráfico con 6 variables puede ser confuso (Tufte, 2001)
- Claridad sobre complejidad: si el mensaje se pierde, simplifica (Few, 2012)
- Guía al lector: usa títulos, subtítulos y leyendas claras
- Prueba con tu audiencia: verifica que el gráfico se entienda
El objetivo no es mostrar todas las variables posibles, sino comunicar insights de manera efectiva. A veces, dos gráficos simples son mejores que uno complejo.
Próximo paso: En Interactividad se explorará la interactividad básica, aprendiendo a agregar tooltips informativos y crear filtros dinámicos con inputs de Observable para que los usuarios puedan explorar los datos de manera interactiva.