Configuración de Ejes


La importancia de los ejes en visualización

Los ejes son elementos fundamentales en cualquier gráfico: sin etiquetas claras y escalas apropiadas, incluso la visualización más hermosa puede ser incomprensible. Un eje bien configurado comunica:

En esta lección aprenderemos a configurar:


Gráfico base

Continuaremos mejorando nuestro gráfico de dispersión de las lecciones anteriores, ahora con estilos aplicados:

Ver código Plot.plot gráfico base
Plot.plot({
  marks: [
    Plot.dot(datos, {
      x: "infant_mortality",
      y: "life_expectancy",
      fill: "steelblue",
      fillOpacity: 0.6,
      stroke: "darkblue",
      strokeWidth: 1.5
    })
  ]
})

El gráfico tiene buen estilo visual, pero los ejes carecen de etiquetas descriptivas y contexto. Vamos a mejorarlo.


Agregando etiquetas a los ejes: label

La propiedad label agrega texto descriptivo a cada eje, explicando qué variable representa.

Ver código Plot.plot con label
Plot.plot({
  x: {
    label: "Mortalidad infantil (por cada 1,000 nacidos vivos)"
  },
  y: {
    label: "Expectativa de vida (años)"
  },
  marks: [
    Plot.dot(datos, {
      x: "infant_mortality",
      y: "life_expectancy",
      fill: "steelblue",
      fillOpacity: 0.6,
      stroke: "darkblue",
      strokeWidth: 1.5
    })
  ]
})

¿Qué cambió?

Se agregaron dos nuevas secciones al objeto principal:

Ahora el gráfico comunica claramente qué representa cada eje.


Mejores prácticas para etiquetas

Incluir unidades

Ser específico (Tufte, 2001)

Mantener brevedad

Usar mayúsculas apropiadamente


Agregando cuadrículas: grid

Las cuadrículas son líneas de referencia que facilitan la lectura de valores específicos en el gráfico.

Ver código Plot.plot con grid
Plot.plot({
  x: {
    label: "Mortalidad infantil (por cada 1,000 nacidos vivos)",
    grid: true
  },
  y: {
    label: "Expectativa de vida (años)",
    grid: true
  },
  marks: [
    Plot.dot(datos, {
      x: "infant_mortality",
      y: "life_expectancy",
      fill: "steelblue",
      fillOpacity: 0.6,
      stroke: "darkblue",
      strokeWidth: 1.5
    })
  ]
})

¿Qué cambió?

Se agregó:

Las líneas verticales (del eje X) y horizontales (del eje Y) ayudan a estimar valores con mayor precisión.


¿Cuándo usar cuadrículas?

Usar cuadrículas cuando:

Evitar cuadrículas cuando:

Recomendación: Generalmente es mejor tener cuadrículas en al menos un eje (usualmente el que representa la variable de interés).


Limitando el rango visible: domain

La propiedad domain permite especificar el rango mínimo y máximo que se mostrará en el eje, útil para hacer zoom o eliminar valores extremos.

Ver código Plot.plot con domain
Plot.plot({
  x: {
    label: "Mortalidad infantil (por cada 1,000 nacidos vivos)",
    grid: true,
    domain: [0, 20]
  },
  y: {
    label: "Expectativa de vida (años)",
    grid: true,
    domain: [68, 86]
  },
  marks: [
    Plot.dot(datos, {
      x: "infant_mortality",
      y: "life_expectancy",
      fill: "steelblue",
      fillOpacity: 0.6,
      stroke: "darkblue",
      strokeWidth: 1.5
    })
  ]
})

¿Qué cambió?

Se agregó:

Los puntos fuera de estos rangos no se muestran, permitiendo enfocarse en la región de interés.

Nota importante: Si no se especifica domain, Observable Plot calcula automáticamente el rango óptimo basado en los datos.


Controlando las marcas del eje: ticks

La propiedad ticks controla cuántas marcas numéricas se muestran en el eje.

Ver código Plot.plot con ticks
Plot.plot({
  x: {
    label: "Mortalidad infantil (por cada 1,000 nacidos vivos)",
    grid: true,
    ticks: 10
  },
  y: {
    label: "Expectativa de vida (años)",
    grid: true,
    ticks: 8
  },
  marks: [
    Plot.dot(datos, {
      x: "infant_mortality",
      y: "life_expectancy",
      fill: "steelblue",
      fillOpacity: 0.6,
      stroke: "darkblue",
      strokeWidth: 1.5
    })
  ]
})

¿Qué cambió?

Se agregó:

Nota: El valor es una sugerencia. Plot puede ajustarlo ligeramente para usar números "redondos".


Guía para el número de ticks

Pocos ticks (3-5):

Ticks moderados (6-10):

Muchos ticks (10+):


Formato en los números: tickFormat

La propiedad tickFormat permite personalizar cómo se muestran los números en el eje usando una función. Un formato apropiado mejora significativamente la legibilidad de los gráficos (Few, 2012).

Formato básico: sin decimales

Ver código Plot.plot con tickFormat
Plot.plot({
  x: {
    label: "Mortalidad infantil (por cada 1,000 nacidos vivos)",
    grid: true,
    tickFormat: d => d.toFixed(0)
  },
  y: {
    label: "Expectativa de vida (años)",
    grid: true,
    tickFormat: d => d.toFixed(1)
  },
  marks: [
    Plot.dot(datos, {
      x: "infant_mortality",
      y: "life_expectancy",
      fill: "steelblue",
      fillOpacity: 0.6,
      stroke: "darkblue",
      strokeWidth: 1.5
    })
  ]
})

¿Qué cambió?

Se agregó:

La función recibe cada valor (d) y devuelve cómo debe mostrarse.


Ejemplos de formatos útiles

Agregar símbolo de porcentaje:

Ver código tickFormat porcentaje
tickFormat: d => `${d}%`
// Resultado: 25%

Formato de millones:

Ver código tickFormat millones
tickFormat: d => `${(d / 1e6).toFixed(1)}M`
// Resultado: 5.2M

Formato de miles con coma:

Ver código tickFormat miles con coma
tickFormat: d => d.toLocaleString()
// Resultado: 1,234,567

Formato de moneda:

Ver código tickFormat moneda
tickFormat: d => `$${d.toFixed(2)}`
// Resultado: $45.99

Notación científica:

Ver código tickFormat notación científica
tickFormat: d => d.toExponential(2)
// Resultado: 1.23e+6

Aplicando formatos a datos económicos

Veamos un ejemplo con PIB (valores grandes):

Ver código Plot.plot con tickFormat económico
Plot.plot({
  x: {
    label: "Producto Interno Bruto (billones USD)",
    grid: true,
    tickFormat: d => `$${(d / 1e9).toFixed(1)}B`,
    type: "log",
  },
  y: {
    label: "Expectativa de vida (años)",
    grid: true
  },
  marks: [
    Plot.dot(datos, {
      x: "gdp_usd",
      y: "life_expectancy",
      fill: "forestgreen",
      fillOpacity: 0.6,
      stroke: "darkgreen",
      strokeWidth: 1.5
    })
  ]
})

Ahora el PIB se muestra en miles de millones (B) de forma legible, nota el uso de la escala logarítmica para poder distribuir los datos utilizando type:"log".


Redondeo automático: nice

La propiedad nice ajusta automáticamente los límites del eje a números "bonitos" o redondos.

Ver código Plot.plot con nice
Plot.plot({
  x: {
    label: "Mortalidad infantil (por cada 1,000 nacidos vivos)",
    grid: true,
    nice: true
  },
  y: {
    label: "Expectativa de vida (años)",
    grid: true,
    nice: true
  },
  marks: [
    Plot.dot(datos, {
      x: "infant_mortality",
      y: "life_expectancy",
      fill: "steelblue",
      fillOpacity: 0.6,
      stroke: "darkblue",
      strokeWidth: 1.5
    })
  ]
})

¿Qué hace nice?

Sin nice: true:

Con nice: true:

Ventaja: Los números del eje son más fáciles de leer y recordar.


Combinando todas las propiedades

Veamos un gráfico con todas las configuraciones de ejes aplicadas:

Ver código Plot.plot con todas las propiedades de ejes
Plot.plot({
  x: {
    label: "Mortalidad infantil (por cada 1,000 nacidos vivos)",
    grid: true,
    domain: [0, 19],
    ticks: 12,
    tickFormat: d => d.toFixed(0),
    nice: true
  },
  y: {
    label: "Expectativa de vida (años)",
    grid: true,
    domain: [68, 86],
    ticks: 8,
    tickFormat: d => d.toFixed(0),
    nice: true
  },
  marks: [
    Plot.dot(datos, {
      x: "infant_mortality",
      y: "life_expectancy",
      fill: "steelblue",
      fillOpacity: 0.6,
      stroke: "darkblue",
      strokeWidth: 1.5
    })
  ]
})

Este gráfico tiene ejes completamente configurados:


Ocultando ejes

En algunos casos específicos, puede ser deseable ocultar un eje completamente usando axis: null.

Ver código Plot.plot con axis null
Plot.plot({
  x: {
    label: "Mortalidad infantil (por cada 1,000 nacidos vivos)",
    grid: true
  },
  y: {
    axis: null
  },
  marks: [
    Plot.dot(datos, {
      x: "infant_mortality",
      y: "life_expectancy",
      fill: "steelblue",
      fillOpacity: 0.6,
      stroke: "darkblue",
      strokeWidth: 1.5
    })
  ]
})

Cuándo usar:

Precaución: Úsalo con cuidado, ya que puede eliminar información importante.


Aplicando a otros tipos de gráficos

Las configuraciones de ejes funcionan igual en todos los tipos de visualizaciones.

Histograma con ejes configurados

Ver código Plot.plot histograma con ejes
Plot.plot({
  x: {
    label: "Expectativa de vida (años)",
    grid: true,
    nice: true
  },
  y: {
    label: "Número de países",
    grid: true,
    ticks: 8
  },
  marks: [
    Plot.rectY(datos, Plot.binX({y: "count"}, {
      x: "life_expectancy",
      fill: "coral",
      fillOpacity: 0.7,
      stroke: "white",
      strokeWidth: 2
    }))
  ]
})

Barras horizontales con ejes configurados

Ver código Plot.plot barras con clamp
Plot.plot({
  x: {
    label: "Expectativa de vida (años)",
    grid: true,
    domain: [45, 90],
    clamp: true,
    nice: true
  },
  y: {
    label: "País"
  },
  marks: [
    Plot.barX(
      datos.slice(10, 20),
      {
        y: "country",
        x: "life_expectancy",
        fill: "forestgreen",
        fillOpacity: 0.8,
        stroke: "darkgreen",
        strokeWidth: 1
      }
    )
  ]
})

Se agregó clamp: true, lo que impide que las barras horizontales y otras visualizaciones similares atraviesen los ejes. Aquí está el ejemplo con clamp: false:

Ver código Plot.plot barras sin clamp
Plot.plot({
  x: {
    label: "Expectativa de vida (años)",
    grid: true,
    domain: [45, 90],
    nice: true
  },
  y: {
    label: "País"
  },
  marks: [
    Plot.barX(
      datos.slice(10, 20),
      {
        y: "country",
        x: "life_expectancy",
        fill: "forestgreen",
        fillOpacity: 0.8,
        stroke: "darkgreen",
        strokeWidth: 1
      }
    )
  ]
})

Ejes en gráficos de múltiples variables

Cuando se grafica una tercera variable (como tamaño de puntos), los ejes siguen funcionando igual:

Ver código Plot.plot con tercera variable
Plot.plot({
  x: {
    label: "Producto Interno Bruto (miles de millones USD)",
    grid: true,
    tickFormat: d => `$${(d / 1e9).toFixed(0)}B`
  },
  y: {
    label: "Expectativa de vida (años)",
    grid: true
  },
  marks: [
    Plot.dot(datos, {
      x: "gdp_usd",
      y: "life_expectancy",
      r: "population",
      fill: "mediumpurple",
      fillOpacity: 0.5,
      stroke: "purple",
      strokeWidth: 1
    })
  ]
})

El tamaño de los puntos representa la población, pero los ejes solo configuran X e Y.


Resumen de propiedades de ejes

Propiedad Tipo Función
label Texto Etiqueta descriptiva del eje
grid Boolean Activa/desactiva cuadrículas (true/false)
domain Array [min, max] Define el rango visible del eje
ticks Número Cantidad aproximada de marcas en el eje
tickFormat Función d => ... Personaliza cómo se muestran los números
nice Boolean Redondea límites a números "bonitos"
axis null Oculta el eje completamente

Conclusiones de la lección

En esta lección se ha explorado la configuración completa de ejes en Observable Plot, transformando un gráfico básico en una visualización profesional y legible.


Conceptos clave

Etiquetas descriptivas

Cuadrículas de referencia

Control del rango

Formato de números


Reflexión final

Los ejes bien configurados son la diferencia entre un gráfico confuso y uno que comunica efectivamente. No son elementos decorativos: son guías esenciales que permiten al lector:

Invertir tiempo en configurar apropiadamente los ejes siempre vale la pena, ya que convierte datos en conocimiento accesible.


Próximo paso: En Contexto y Estructura se explorará cómo agregar contexto global al gráfico mediante títulos, subtítulos, dimensiones y márgenes, completando así la estructura profesional de una visualización.


Bibliografía

Few, S. (2012). Show Me the Numbers: Designing Tables and Graphs to Enlighten (2a ed.). Analytics Press.
Tufte, E. (2001). The Visual Display of Quantitative Information (2a ed.). Graphics Press.