Docs / Build Workflow

Visualization — report_matrix

Cuándo usar report_matrix

report_matrix es la elección correcta cuando la audiencia necesita un reporte estructurado con filas agrupadas, secciones anidadas, subtotales y totales de grupo. Está diseñado para dashboards modo document y PDF export, mientras igual soporta click-to-filter dentro de dashboards interactivos.

Usa grid en su lugar cuando las filas no necesitan agrupamiento. Usa una viz tipo chart cuando la pregunta es sobre una métrica única entre categorías en vez de un reporte tabular estructurado.

Mapping

report_matrix toma su estructura de columnas del resultado de la query. No hay un bloque mapping requerido; la configuración de matrix vive bajo el bloque matrix en su lugar.

Columnas & presentación

Estas keys controlan qué columnas muestra el matrix y cómo renderiza cada columna:

  • matrix.key_columns — array de nombres de columna renderizados como key cells (bold, coloreo basado en polaridad). Usalo para la columna de métrica que los readers tienen que enfocar (ej. attainment %, conversion rate).
  • matrix.cross_filter — boolean, default true. Setea a false para excluir el matrix de la emisión de click (mira Comportamiento de cross-filter abajo).
  • matrix.trend_columns — array de nombres de columna renderizados con un trend icon (up / down / dash) al lado del valor.
  • matrix.labels — objeto mapeando nombre de columna a display label (overridea el nombre raw de columna en el header).
  • matrix.column_formats — objeto mapeando nombre de columna a una format key.
  • matrix.formats — objeto mapeando format key a un pattern (indirección de dos pasos, como grid.formats).
  • matrix.column_widths — objeto mapeando nombre de columna a un ancho ("150px", "20%", o numérico).
  • matrix.uniform_column_widths — boolean o "auto". Cuando está seteado, todas las columnas comparten el mismo ancho auto-fit.
  • matrix.uniform_column_widths_min_px — entero. Default 80.
  • matrix.uniform_column_widths_max_px — entero. Default 520.

Tabla de summary

El matrix puede renderizar un summary comparativo arriba de las filas de detalle:

  • matrix.show_summary — boolean. Default true.
  • matrix.summary_title — título string arriba del summary.
  • matrix.summary_columns — array de nombres de columna incluidos en el summary.

Agrupamiento & secciones

Dos maneras de organizar las filas: agrupamiento automático por una columna, o secciones manuales.

Agrupamiento automático

  • matrix.group_by — nombre de columna. Agrupa las filas resultado por este field; cada grupo se vuelve una sección colapsable.
  • matrix.group_key_field — nombre de columna a renderizar como la primera columna dentro de cada sección de grupo.
  • matrix.group_columns — array de nombres de columna renderizados dentro de cada grupo.

Secciones manuales

matrix:
  sections:
    - id: revenue
      title: Revenue breakdown
      columns: [period, units, revenue]
    - id: cost
      title: Cost breakdown
      columns: [period, cogs, opex]

Totales

Los totales viven en dos hermanos bajo matrix: group_totals (una fila por sección de grupo) y overall_totals (una fila entre todos los grupos). Ambos comparten el mismo shape:

  • enabled — boolean.
  • label — string. Default "TOTAL".
  • columns — array de nombres de columna a sumar. Si está vacío, las columnas numéricas se suman automáticamente.
  • computed — array de objetos de field computado renderizados al lado de los sums. Cada item:
    • field — nombre del field output.
    • type"ratio" o "percent_delta".
    • numerator — nombre del field para el dividendo (ratio) o período actual (delta).
    • denominator — nombre del field para el divisor (ratio) o baseline (delta).
matrix:
  group_totals:
    enabled: true
    label: TOTAL
    columns: [units, revenue]
    computed:
      - field: attainment_pct
        type: percent_delta
        numerator: revenue
        denominator: budget
  overall_totals:
    enabled: true
    label: GRAND TOTAL
    columns: [units, revenue]

Behavior

matrix.behavior controla cómo se expanden las secciones y cómo renderiza el matrix para PDF export:

  • web_mode"all_open" (cada sección expandible independientemente), "single_open" (abrir una sección cierra las otras), o "expand_all" (todo abierto, headers inertes). Omite la key para el comportamiento accordion por defecto.
  • default_open"all" o un id de sección específico. Qué secciones empiezan expandidas en first load.
  • pdf_expand_all — boolean. Default false. Crítico para PDF export: sin esto, los grupos colapsados desaparecen del documento impreso.

format

Usa matrix.column_formats + matrix.formats como el camino primario de formatting; el field format root se chequea solo como fallback.

Comportamiento de cross-filter

  • Clickear una celda del cuerpo cuya columna está declarada como parámetro en una firma de source del archivo de model propio de esta viz emite un pill { field: <nombre de columna>, value: <valor de celda> }.
  • Las celdas en filas de group totals y overall totals no son clickeables — agregan entre múltiples valores key, así que un click sería ambiguo.
  • Las celdas en trend columns (renderizadas con badges de dirección up/down) no son clickeables — muestran dirección sobre un valor numérico, no un pick categórico.
  • Los headers de sección (auto-agrupados vía matrix.group_by o hechos a mano vía matrix.sections) no son clickeables en esta versión. El click de <details> está reservado para expand/collapse.
  • Los dashboards en modo document suprimen el cableo de cell-click enteramente — el render document/PDF no tiene target interactivo.
  • Deshabilita por viz con matrix.cross_filter: false.

Mira Cross-filtering para el mecanismo completo.

Ejemplo trabajado

Un matrix de revenue agrupado por categoría con las marcas de cada categoría como filas de detalle. El ticket promedio en las filas de totales es un ratio computed — sumar un promedio estaría mal, así que se re-deriva de las columnas sumadas:

id: ec_category_brand_matrix
title: Revenue matrix by category
query: "models/ec_category_brand_matrix.malloy::by_category_brand"
type: report_matrix
matrix:
  show_summary: false
  group_by: category
  group_key_field: brand
  group_columns:
    - revenue
    - order_count
    - avg_ticket
    - revenue_prev_year
    - yoy_delta_pct
  key_columns: [revenue, yoy_delta_pct]
  trend_columns: [yoy_delta_pct]
  group_totals:
    enabled: true
    label: TOTAL
    columns: [revenue, order_count, revenue_prev_year]
    computed:
      - field: avg_ticket
        type: ratio
        numerator: revenue
        denominator: order_count
  overall_totals:
    enabled: true
    label: GRAND TOTAL
    columns: [revenue, order_count, revenue_prev_year]
  labels:
    brand: Brand
    revenue: Revenue
    order_count: Orders
    avg_ticket: Avg ticket
    revenue_prev_year: Revenue LY
    yoy_delta_pct: YoY
  column_formats:
    revenue: currency
    avg_ticket: currency
    revenue_prev_year: currency
    yoy_delta_pct: percent
  formats:
    currency: "$#,##0"
    percent: "#,##0.0%"
  behavior:
    web_mode: all_open
    default_open: all
    pdf_expand_all: true
pagination:
  page_size: 50
published: true

Notas de diseño

  • Para PDF export, setea matrix.behavior.pdf_expand_all: true para que cada grupo imprima expandido.
  • Lista las columnas a sumar explícitamente en group_totals.columns / overall_totals.columns — la forma vacía auto-suma cada columna numérica, incluyendo números tipo ID.
  • Los campos de total computado referencian columnas presentes en las filas sumadas — tanto numerator como denominator.
  • Controla el estado de primera carga con matrix.behavior.default_open: "all", o el id de una sección específica.
  • Usa la indirección matrix.column_formats + matrix.formats para que el mismo pattern de moneda / porcentaje aplique en todos lados donde corresponde.