Parametrizar informes
El problema
Tienes un informe mensual de ventas. La estructura es siempre la misma: portada, sección por región, gráfico anual, tabla resumen. Lo único que cambia: el mes y el subconjunto de datos.
Sin parametrización, copias el .qmd, cambias 5 valores hard-coded y renderizas. Multiplicado por 12 meses × 6 regiones = 72 archivos casi idénticos. Insostenible.
Con parametrización: un solo .qmd + un script que lo renderiza 72 veces con distintos parámetros. Cambios estructurales se hacen una vez.
Sintaxis básica
En el front matter:
---
title: "Informe regional"
format: html
params:
region: "Norte"
periodo: "2024-Q4"
destacar_top: 10
---Desde un chunk R:
params$region # "Norte"
params$periodo # "2024-Q4"
params$destacar_top # 10Y desde Python:
params["region"]params es una lista (R) o dict (Python) con las claves del YAML. Los valores son los defaults del informe.
Usar parámetros en el código
library(dplyr)
library(ggplot2)
datos_region <- ventas |>
filter(region == params$region,
periodo == params$periodo)
ggplot(datos_region, aes(mes, ventas)) +
geom_line() +
labs(title = paste("Ventas de", params$region),
subtitle = params$periodo)Cada vez que renderices con un region distinto, el filtro cambia, el título cambia, todo el informe se adapta. Es el mismo documento sirviendo de plantilla.
Renderizar con parámetros distintos
Desde la CLI
quarto render informe.qmd -P region:Sur -P periodo:"2024-Q3"-P clave:valor sobreescribe el default del YAML. Funciona en bash y PowerShell.
Desde R
quarto::quarto_render(
input = "informe.qmd",
output_file = "informe-sur.html",
execute_params = list(region = "Sur", periodo = "2024-Q3")
)execute_params toma una lista R que se convierte a YAML internamente.
Desde Python
import subprocess
subprocess.run([
"quarto", "render", "informe.qmd",
"-P", "region:Sur", "-P", "periodo:2024-Q3"
])No hay API Python nativa todavía, se llama a la CLI desde Python con subprocess.
Output a archivo distinto
Por defecto, informe.qmd renderiza a informe.html. Con varios parámetros, vas a sobrescribir el output cada vez. Soluciones:
output-file en YAML
Dinámico:
params:
region: "Norte"
periodo: "2024-Q4"Y desde el chunk:
quarto::quarto_render(
input = "informe.qmd",
output_file = paste0("informe-", params$region, "-", params$periodo, ".html"),
execute_params = list(region = "Sur", periodo = "2024-Q3")
)Output: informe-Sur-2024-Q3.html. Conserva la versión anterior si renderizas otro region.
--output en CLI
quarto render informe.qmd \
-P region:Sur -P periodo:2024-Q3 \
--output informe-sur-Q3.htmlLotes: el script que genera N informes
El uso típico de parametrización es producción en lote. Patrón en R:
library(tidyverse)
configs <- expand_grid(
region = c("Norte", "Sur", "Este", "Oeste"),
periodo = c("2024-Q1", "2024-Q2", "2024-Q3", "2024-Q4")
)
walk2(configs$region, configs$periodo, function(r, p) {
quarto::quarto_render(
input = "informe.qmd",
output_file = paste0("informes/informe-", r, "-", p, ".html"),
execute_params = list(region = r, periodo = p),
quiet = TRUE
)
message("✓ ", r, " ", p)
})16 informes en una sola pasada. expand_grid crea todas las combinaciones. walk2 itera sobre dos vectores paralelos. quiet = TRUE reduce ruido del log.
Para Python:
import subprocess
from itertools import product
regiones = ["Norte", "Sur", "Este", "Oeste"]
periodos = ["2024-Q1", "2024-Q2", "2024-Q3", "2024-Q4"]
for r, p in product(regiones, periodos):
subprocess.run([
"quarto", "render", "informe.qmd",
"-P", f"region:{r}",
"-P", f"periodo:{p}",
"--output", f"informes/informe-{r}-{p}.html"
])
print(f"✓ {r} {p}")Validación de parámetros
Defensa razonable contra parámetros mal pasados:
valores_validos <- c("Norte", "Sur", "Este", "Oeste")
if (!params$region %in% valores_validos) {
stop("Region '", params$region, "' no válida. ",
"Valores: ", paste(valores_validos, collapse = ", "))
}Sin esto, un valor incorrecto produce un informe vacío o con errores silenciosos, datos filtrados a 0 filas, gráficos en blanco. Falla pronto y claro.
Parámetros condicionales
Mostrar contenido según parámetro:
#| label: solo-bonus
#| echo: false
#| eval: !expr params$incluir_bonus
# Este chunk solo se ejecuta si incluir_bonus = TRUE
generar_seccion_extra()!expr evalúa la expresión R como condición. Útil para informes resumen vs detallado desde la misma plantilla.
En texto markdown, condicional con shortcode:
::: {.content-visible when-meta="incluir_apendice"}
## Apéndice
Contenido solo si `incluir_apendice: true`.
:::Tipos de parámetros que admite YAML
params:
string_simple: "Norte"
numero: 12
decimal: 0.05
booleano: true
lista:
- "uno"
- "dos"
- "tres"
fecha: 2024-12-31
null_explicito: nullPara listas y fechas, conviene convertir explícitamente en el código:
fecha_inicio <- as.Date(params$fecha)
mis_regiones <- unlist(params$lista)Default vs override
El YAML define defaults. Cuando renderizas sin pasar -P, esos defaults se usan. Cuando pasas -P region:Sur, solo ese parámetro se sobreescribe. Los demás mantienen el default.
Patrón útil: defaults para render local de prueba (Norte, Q4), parámetros explícitos para producción (todos los combos).
Workflow recomendado
Para informes parametrizados:
proyecto/
├── informe.qmd ← plantilla con params
├── generar_lote.R ← script que renderiza todos
├── datos/
│ └── ventas.csv
└── informes/
└── (outputs generados, no versionados)
informe.qmd con defaults para development. generar_lote.R para producción. Carpeta informes/ en .gitignore (output regenerable).
Trampas habituales
- Hard-coding valores en el código olvidando el
params$. La plantilla deja de ser plantilla. Cualquier valor “de configuración” debe pasar porparams. - Sobrescribir output sin querer. Si renderizas 10 veces sin
output_file, te quedas con el último. Define output dinámico desde el principio. - No validar parámetros. Un
region: "Estte"(con typo) filtra a 0 filas y el informe queda vacío sin error. Valida al inicio. - Tipos mal interpretados desde CLI.
-P x:falsepuede llegar como string"false"en R/Python, no como booleano. Convierte explícito:as.logical(params$x). - YAML estricto con guiones, dos puntos. Los strings con caracteres especiales necesitan comillas:
region: "Norte (sub-1)". Sin comillas, el:rompe el parseo.
En la siguiente entrega
Tienes la plantilla parametrizada. Lo siguiente es reusar fragmentos entre documentos: includes para insertar pedazos comunes, child documents para descomponer un documento grande. Es lo que mantiene un proyecto Quarto grande manejable. Lo siguiente.