Cuándo usar heatmap
Heatmap es la elección correcta cuando quieres 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.
Usa grid en su lugar cuando la audiencia necesita leer los números reales y una de las dimensions es de alta cardinalidad. Usa 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
Las extracciones de time-bucket como hour-of-day y day-of-week son funciones de dialecto — calcúlalas como columnas en una source de raw-SQL para que el heatmap consuma fields ya listos (este shape también porta a Postgres/MySQL intercambiando las funciones de extracción):
# models/ec_orders_activity.malloy
##! experimental.parameters
source: ec_orders_activity() is ecommerce.sql("""
SELECT
EXTRACT(HOUR FROM created_at) AS hour_of_day,
FORMAT_TIMESTAMP('%a', created_at) AS day_of_week,
MIN(EXTRACT(DAYOFWEEK FROM created_at)) AS day_order,
COUNT(*) AS order_count
FROM `bigquery-public-data.thelook_ecommerce.orders`
GROUP BY 1, 2
""") extend {
view: by_day_hour is {
select: hour_of_day, day_of_week, order_count, day_order
order_by: day_order asc, hour_of_day asc
}
}
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. Estiliza los labels conchart.labelabajo.chart.cross_filter_emit—"x"o"y". Heatmap tiene dos ejes categóricos, así que tienes que elegir cuál valor se emite al click. Requerido cada vez quechart.cross_filterno es explícitamentefalse; el schema rechaza un bloque chart que no tenga ninguno.chart.cross_filter— boolean, defaulttrue. Setea afalsepara deshabilitar la emisión de click entera; en ese casocross_filter_emitno 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). Usa{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 confía 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.valueoformat[<value_field_name>]— pattern para labels de celda y valores de tooltip.formaten root — fallback.
Comportamiento de cross-filter
- El click emite un valor solo cuando
chart.cross_filter_emitestá 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 una firma de source del archivo de model propio de esta viz.
- Deshabilita por viz con
chart.cross_filter: false(o simplemente dejacross_filter_emitunset).
Mira 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 (setea min / max explícitos):
chart:
visual_map:
show: true
min: 0
max: 5000
in_range:
color: ["#e0f7f4", "#0d9488"]
Notas de diseño
- Cuando un outlier domina la escala de color, setea
visual_map.maxpara recortarlo — los valores sobre el tope renderizan con el color máximo. - Para labels sobre celdas oscuras, setea un
chart.label.colorcontrastante, o apaga los labels de celda y apoyate en el tooltip. - Un heatmap emite un eje por click (
cross_filter_emit: "x"o"y") — cuando la interacción necesita ambas coordenadas, usa un grid. - El
visual_map.in_range.colorexpuesto es un gradiente low-to-high — para escalas divergentes, codifica la divergencia en el valor mismo (ej. un delta con signo).