Heatmap
ChartUna matriz de columna × fila, donde el color es el valor. Actividad por hora y día, retención por cohortes, un calendario de commits.
Actividad por hora y día
168 celdas (24 horas × 7 días). El patrón salta a la vista: la banda de oficina de lunes a viernes, y las noches del finde. Pasa el ratón por una celda —una sola, no 168 escuchas— para ver el número exacto.
| Categoría | sesiones |
|---|---|
| 00 | 8 |
| 01 | 18 |
| 02 | 18 |
| 03 | 9 |
| 04 | 0 |
| 05 | 0 |
| 06 | 4 |
| 07 | 15 |
| 08 | 19 |
| 09 | 74 |
| 10 | 63 |
| 11 | 83 |
| 12 | 63 |
| 13 | 75 |
| 14 | 81 |
| 15 | 77 |
| 16 | 91 |
| 17 | 58 |
| 18 | 60 |
| 19 | 9 |
| 20 | 18 |
| 21 | 18 |
| 22 | 7 |
| 23 | 0 |
| 00 | 18 |
| 01 | 18 |
| 02 | 9 |
| 03 | 0 |
| 04 | 0 |
| 05 | 4 |
| 06 | 15 |
| 07 | 19 |
| 08 | 12 |
| 09 | 63 |
| 10 | 58 |
| 11 | 88 |
| 12 | 75 |
| 13 | 81 |
| 14 | 77 |
| 15 | 66 |
| 16 | 83 |
| 17 | 60 |
| 18 | 71 |
| 19 | 18 |
| 20 | 18 |
| 21 | 7 |
| 22 | 0 |
| 23 | 0 |
| 00 | 18 |
| 01 | 9 |
| 02 | 0 |
| 03 | 0 |
| 04 | 4 |
| 05 | 15 |
| 06 | 19 |
| 07 | 12 |
| 08 | 1 |
| 09 | 58 |
| 10 | 63 |
| 11 | 100 |
| 12 | 81 |
| 13 | 77 |
| 14 | 66 |
| 15 | 58 |
| 16 | 85 |
| 17 | 71 |
| 18 | 80 |
| 19 | 18 |
| 20 | 7 |
| 21 | 0 |
| 22 | 0 |
| 23 | 6 |
| 00 | 9 |
| 01 | 0 |
| 02 | 0 |
| 03 | 4 |
| 04 | 15 |
| 05 | 19 |
| 06 | 12 |
| 07 | 1 |
| 08 | 0 |
| 09 | 63 |
| 10 | 75 |
| 11 | 106 |
| 12 | 77 |
| 13 | 66 |
| 14 | 58 |
| 15 | 60 |
| 16 | 96 |
| 17 | 80 |
| 18 | 80 |
| 19 | 7 |
| 20 | 0 |
| 21 | 0 |
| 22 | 6 |
| 23 | 17 |
| 00 | 0 |
| 01 | 0 |
| 02 | 4 |
| 03 | 15 |
| 04 | 19 |
| 05 | 12 |
| 06 | 1 |
| 07 | 0 |
| 08 | 1 |
| 09 | 75 |
| 10 | 81 |
| 11 | 102 |
| 12 | 66 |
| 13 | 58 |
| 14 | 60 |
| 15 | 71 |
| 16 | 105 |
| 17 | 80 |
| 18 | 69 |
| 19 | 0 |
| 20 | 0 |
| 21 | 46 |
| 22 | 57 |
| 23 | 59 |
| 00 | 8 |
| 01 | 16 |
| 02 | 27 |
| 03 | 31 |
| 04 | 24 |
| 05 | 13 |
| 06 | 8 |
| 07 | 13 |
| 08 | 25 |
| 09 | 31 |
| 10 | 27 |
| 11 | 16 |
| 12 | 8 |
| 13 | 10 |
| 14 | 21 |
| 15 | 30 |
| 16 | 30 |
| 17 | 19 |
| 18 | 9 |
| 19 | 9 |
| 20 | 18 |
| 21 | 69 |
| 22 | 71 |
| 23 | 63 |
| 00 | 16 |
| 01 | 27 |
| 02 | 31 |
| 03 | 24 |
| 04 | 13 |
| 05 | 8 |
| 06 | 13 |
| 07 | 25 |
| 08 | 31 |
| 09 | 27 |
| 10 | 16 |
| 11 | 8 |
| 12 | 10 |
| 13 | 21 |
| 14 | 30 |
| 15 | 30 |
| 16 | 19 |
| 17 | 9 |
| 18 | 9 |
| 19 | 18 |
| 20 | 29 |
| 21 | 71 |
| 22 | 63 |
| 23 | 52 |
<x-kore::chart :data="$actividad" x="hora" height="14rem" aria-label="Actividad por hora y día">
<x-kore::chart.heatmap y="sesiones" row="dia" :buckets="6" />
</x-kore::chart>
{{-- Formato «largo», el de un GROUP BY: una fila por celda.
['dia' => 'Lun', 'hora' => '09', 'sesiones' => 72] --}}<x-kore::chart :data="$actividad" x="hora" height="14rem" aria-label="Actividad por hora y día">
<x-kore::chart.heatmap y="sesiones" row="dia" :buckets="6" />
</x-kore::chart>
{{-- Formato «largo», el de un GROUP BY: una fila por celda.
['dia' => 'Lun', 'hora' => '09', 'sesiones' => 72] --}}Retención por cohortes
Cada fila es una cohorte (el mes en que llegaron); cada columna, las semanas desde entonces. El color se apaga de izquierda a derecha: la gente se va. Menos buckets, escala más gruesa.
| Categoría | retencion |
|---|---|
| S0 | 100 |
| S1 | 67 |
| S2 | 50 |
| S3 | 38 |
| S4 | 28 |
| S5 | 21 |
| S6 | 16 |
| S0 | 100 |
| S1 | 63 |
| S2 | 46 |
| S3 | 34 |
| S4 | 24 |
| S5 | 17 |
| S6 | 12 |
| S0 | 100 |
| S1 | 59 |
| S2 | 42 |
| S3 | 30 |
| S4 | 20 |
| S5 | 13 |
| S6 | 8 |
| S0 | 100 |
| S1 | 55 |
| S2 | 38 |
| S3 | 26 |
| S4 | 16 |
| S5 | 9 |
| S6 | 8 |
<x-kore::chart :data="$cohortes" x="semana" height="10rem" aria-label="Retención por cohortes">
<x-kore::chart.heatmap y="retencion" row="cohorte" :buckets="5" />
</x-kore::chart><x-kore::chart :data="$cohortes" x="semana" height="10rem" aria-label="Retención por cohortes">
<x-kore::chart.heatmap y="retencion" row="cohorte" :buckets="5" />
</x-kore::chart>Formato de datos: el largo
Tres canales, no uno: la columna es el x del gráfico, la fila es row, y el valor es y. El orden de columnas y filas es el orden en que aparecen en el dato — ordena por (fila, columna) en tu SQL y salen ordenadas.
$actividad = [
['dia' => 'Lun', 'hora' => '09', 'sesiones' => 72],
['dia' => 'Lun', 'hora' => '10', 'sesiones' => 68],
// ...
];$actividad = [
['dia' => 'Lun', 'hora' => '09', 'sesiones' => 72],
['dia' => 'Lun', 'hora' => '10', 'sesiones' => 68],
// ...
];Un cruce sin dato no es un cero. Si falta una combinación (fila, columna) en el array, la celda se queda sin color y se ve el fondo. Pintarla del tono más claro diría «poco», y es «nada».
El color se cuantiza, no se interpola
El valor cae en uno de N escalones (:buckets, entre 3 y 7) y la celda lleva un data-bucket; el color lo pone el CSS con la rampa secuencial (--kore-seq-*).
PHP no calcula un solo color: así el tema sigue cambiando sin ejecutar JavaScript, y de paso una escala de escalones se lee mejor — un degradado continuo obliga a mirar la leyenda para cada celda.
El hover va por delegación: un heatmap de 365×7 son 2.555 celdas, y un listener por celda cuesta caro. Hay un solo pointermove en la rejilla; el resalte de la celda es :hover de CSS puro.
Props
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
y
|
string | — | La columna del valor (el color de la celda) |
row
|
string | — | La columna de la fila (la columna la da el x del gráfico) |
buckets
|
int | 5 | Cuántos escalones de color, de 3 a 7 |
show
|
bool | true | Apaga la marca |