Docs / Build Workflow

Visualization — heatmap

Cuándo usar heatmap

Heatmap es la elección correcta cuando querés renderizar un measure a través de dos dimensions categóricas o temporales a la vez. Usos comunes: day-of-week vs hour-of-day para patterns de actividad; channel vs region para densidad de revenue; categoría de producto vs mes para estacionalidad.

Usá grid en su lugar cuando la audiencia necesita leer los números reales y una de las dimensions es de alta cardinalidad. Usá scatter cuando las dimensions son continuas en vez de categóricas.

Mapping

  • mapping.x — requerido. Field del eje-columna (un tick por valor distinto).
  • mapping.y — requerido. Field del eje-fila.
  • mapping.value — requerido. Field numérico que maneja la intensidad de color de cada celda.
mapping:
  x: hour_of_day
  y: day_of_week
  value: order_count

Shortcuts de chart

El bloque chart es tipado y cerrado.

  • chart.show_cell_labels — boolean. Renderiza el valor de la celda adentro de cada celda. Estilizá los labels con chart.label abajo.
  • chart.cross_filter_emit"x" o "y". Heatmap tiene dos ejes categóricos, así que tenés que elegir cuál valor se emite al click. Requerido cada vez que chart.cross_filter no es explícitamente false; el schema rechaza un bloque chart que no tenga ninguno.
  • chart.cross_filter — boolean, default true. Seteá a false para deshabilitar la emisión de click entera; en ese caso cross_filter_emit no es requerido.
  • chart.height — altura en pixels del container de la viz.

Color scale

chart.visual_map es un objeto que controla el gradiente de color y la legend opcional de color-scale:

  • show — boolean. Muestra la legend de color-scale al lado del chart.
  • orient"horizontal" | "vertical".
  • min, max — piso / techo explícitos. Overridean el rango derivado de datos — útil cuando varios heatmaps en el mismo dashboard necesitan compartir una escala.
  • left / right / top / bottom — número de pixels o string de porcentaje para placear la legend de color-scale.
  • in_range.color — array de strings hex: los stops del gradiente de low a high. Dos stops producen un gradiente simple low-to-high.
  • text_style — estilo de texto para los labels de la color-scale.
chart:
  visual_map:
    show: true
    orient: vertical
    in_range:
      color: ["#e0f7f4", "#0d9488"]

Labels de celda

chart.label estiliza el label numérico por-celda cuando chart.show_cell_labels está prendido:

  • position, rotate, color, font_size, font_weight.
  • formatter — template string (sin callbacks). Usá {c} para el valor.
  • distance, align, vertical_align, clip.

Los labels de celda son útiles cuando el heatmap es chico y la audiencia necesita el número exacto; en heatmaps densos los labels se vuelven ruido — dejalos apagados y confiá en el tooltip.

Legend & tooltip

chart.legend y chart.tooltip comparten el mismo shape que en bar. Para heatmap el tooltip con trigger: item revela una celda a la vez con ambos valores de eje y el valor de celda.

Ejes

chart.x_axis y chart.y_axis comparten el mismo shape:

  • name, name_location, name_gap.
  • axis_label.show, axis_label.rotate, axis_label.interval, axis_label.color, axis_label.font_size, axis_label.font_weight, axis_label.formatter, axis_label.max_chars.

format

  • format.value o format[<value_field_name>] — pattern para labels de celda y valores de tooltip.
  • format en root — fallback.

Comportamiento de cross-filter

  • El click emite un valor solo cuando chart.cross_filter_emit está seteado a "x" o "y".
  • El eje elegido se vuelve el field de cross-filter; el label clickeado se vuelve el valor.
  • El field clickeado tiene que estar declarado como parámetro en al menos un model usado por el dashboard.
  • Deshabilitá por viz con chart.cross_filter: false (o simplemente dejá cross_filter_emit unset).

Mirá Cross-filtering para el mecanismo completo.

Ejemplos trabajados

Actividad por hora y día de semana:

id: orders_by_day_hour
title: Orders by Day and Hour
query: "models/ec_orders.malloy::by_day_hour"
type: heatmap
mapping:
  x: hour_of_day
  y: day_of_week
  value: order_count
chart:
  height: 320
  show_cell_labels: true
  cross_filter_emit: x
  visual_map:
    show: true
    orient: vertical
    in_range:
      color: ["#e0f7f4", "#0d9488"]
  x_axis:
    name: Hour
  y_axis:
    name: Day
format:
  order_count: "#,##0"
published: true

Color scale compartida entre múltiples heatmaps (seteá min / max explícitos):

chart:
  visual_map:
    show: true
    min: 0
    max: 5000
    in_range:
      color: ["#e0f7f4", "#0d9488"]

Errores comunes

  • El chart se ve vacío aunque la query tiene filas. Asegurate que tanto mapping.x como mapping.y contengan los fields correctos y que el field de valor de celda no sea null.
  • La color scale está dominada por un outlier. Seteá visual_map.max para clipear la escala; los valores arriba del cap renderizan con el color top.
  • Los labels son ilegibles en celdas oscuras. Seteá un chart.label.color que contraste, o apagá los labels de celda y confiá en el tooltip.
  • El click no hace nada. Heatmap requiere chart.cross_filter_emit seteado a "x" o "y". Sin eso, no se dispara ningún evento sin importar cross_filter.
  • El click debería emitir tanto x como y. Heatmap puede emitir solo un eje. Si necesitás los dos, usá un grid.
  • Color scale divergente con un midpoint. El visual_map.in_range.color expuesto es un gradiente simple low-to-high; para escalas divergentes, codificá la divergencia en el valor subyacente (ej. delta con signo).