Todo lo que hace el comando urg-forecast son unas pocas funciones sobre DataFrames. Esta página va de lo más simple a lo más detallado: cada función del paquete urgencias_core, desde instalarlo hasta comparar modelos, con su explicación a la izquierda y un ejemplo con su salida a la derecha; al final, las recetas para extenderlo con tu propio modelo o una variable externa. El mapa del paquete está en Arquitectura y hay scripts completos en Ejemplos.
Primeros pasos
Todo el paquete trabaja con DataFrames de pandas. Los ejemplos de esta página se ejecutan tal cual, en orden, con el snapshot del DEIS que trae el paquete (offline=True: Hospital de Puerto Montt y Hospital de Frutillar), así que puedes copiarlos y obtener lo mismo. Sin offline=True leen la copia semanal del repositorio, con cualquier establecimiento.
Python 3.11 o 3.12. Instala el paquete desde PyPI; trae el comando urg-forecast y la biblioteca urgencias_core. Las funciones de uso común se importan directo desde urgencias_core.
Casi todo recibe la misma entrada: un DataFrame con timestamp (el lunes que cierra cada semana DEIS: los 7 días que terminan ese lunes) y count (atenciones). Solo semanas completas; 2020 y 2021 quedan fuera por la pandemia. Si traes tus propios datos, arma ese mismo DataFrame y todo lo demás funciona igual.
from urgencias_core import load_deis, weekly_series
df =load_deis(["24-105"],offline=True)
semanal =weekly_series(df,"24-105")
print(semanal.tail(3))
Salida
timestamp count
247 2026-10-05 1966
248 2026-10-12 1986
249 2026-10-19 2068
Datos
De dónde vienen las series: el DEIS (copia semanal del repositorio, archivos completos o snapshot incluido) y el listado de establecimientos.
Filas DEIS (diarias, por causa y grupo de edad) de uno o más establecimientos. Acepta el código en cualquiera de sus formas (24-105 o 124105). La fuente usada queda en df.attrs['source'].
codes
lista de códigos DEIS
start_year
primer año (por defecto 2022; 2020-2021 siempre se excluyen)
offline
usar el snapshot incluido, sin red
source
"repo" (copia semanal, liviana) o "deis" (archivos completos)
cache_dir
dónde guardar las descargas
Devuelve: DataFrame con date, facility_code, facility_name, cause_group, age_group, count. Lanza NoDataError si no hay datos.
Las atenciones totales de un establecimiento por semana DEIS. Recorta las semanas incompletas de los extremos: la última semana suele llegar con días faltantes y parecería una caída.
Las formas de un mismo código. El DEIS publica los establecimientos más antiguos con el código SS-NNN (los dos primeros dígitos indicaban el Servicio de Salud) y también como 1SSNNN; los creados después tienen solo un código de 6 dígitos. Todas las funciones aceptan cualquiera de las formas.
code
código DEIS
Devuelve: conjunto de formas equivalentes.
from urgencias_core.data.deis import facility_code_variants
El listado de establecimientos de la copia semanal: código, nombre, tipo (Hospital, SAPU, SAR, SUR…), región, comuna, servicio de salud y fechas con datos. Es lo que usa urg-forecast buscar. Necesita red.
Devuelve: DataFrame con una fila por establecimiento.
from urgencias_core.data.mirror import mirror_facilities
Este ejemplo necesita red, así que no se ejecuta al generar la página.
Análisis
Cómo ha sido la demanda, antes de pronosticar. Funciones puras: reciben la serie semanal y devuelven un DataFrame. Es lo que hace urg-forecast analizar.
Una fila por año. El cambio compara las mismas semanas del año anterior, así un año incompleto (enero a marzo) se compara con enero a marzo y no con un año completo.
weekly
serie semanal
Devuelve: semanas, complete, total, promedio semanal, change_pct, semana más alta.
from urgencias_core.analysis import yearly_summary
El año típico: para cada semana del año, el promedio y el rango entre años, y index: cuánto se aleja esa semana del nivel de su propio año (1,15 = 15 % sobre el nivel). Así el crecimiento de un año a otro no se confunde con la estación.
weekly
serie semanal
years
usar solo los últimos años
Devuelve: una fila por semana: mean, low, high, years, index.
from urgencias_core.analysis import seasonal_profile
level es el promedio de las últimas 52 semanas: al promediar un año completo desaparece la estación y queda la tendencia. year_over_year compara cada semana con la misma de un año antes (sumas de 4 semanas).
weekly
serie semanal
window
semanas del promedio (52)
Devuelve:timestamp, count, level, change_pct.
from urgencias_core.analysis import level, year_over_year
Cada modelo pronostica semanas pasadas que ya se conocen (ventanas tan largas como el horizonte, hasta 26 semanas) y se pronostica con Ensamble, la mediana de AutoARIMA, Armónico y MSTL, reajustado con toda la historia: en 40 hospitales rindió más que elegir el mejor modelo de cada uno. Los demás quedan en backtest como referencia. select_by elige en cambio el mejor según un criterio, y con calibrate=True las bandas se ensanchan según el error que tuvo en esas ventanas.
history
serie semanal
horizon_weeks
semanas a pronosticar
models
nombre → fábrica; por defecto default_models(): Ensamble y sus referencias. Sin Ensamble entre ellos, gana el de menor pérdida P80
origins, step
número de ventanas (3) y semanas entre ellas (8); al elegir, más ventanas dan una elección más estable, no más acertada
calibrate
ensanchar los intervalos según el backtest (False por defecto: en 40 hospitales empeoró la pérdida P80 en la mayoría)
select_by
None (por defecto): Ensamble. Para elegir, una columna: "qloss_80", "qloss_50", "qloss_90", "qloss_95", "qloss_mean", "wis", "mae", o una función que reciba la tabla del backtest y devuelva un modelo
quantiles
cuantiles del backtest y del pronóstico; por defecto P50 a P95, y de P5 a P95 con select_by="wis"
Devuelve:ForecastResult: best (el modelo que pronostica), backtest (error por modelo), forecast (timestamp, q50, q80, q90, q95), coverage80, interval_scale (vacío si no se calibró).
from urgencias_core import run_forecast
nombre ="Hospital de Puerto Montt"
res =run_forecast(semanal,12,code="24-105",name=nombre)
q50 es el valor central: la mitad de las veces el real queda bajo él. q80 y q95 son los valores que, con 80 % y 95 % de probabilidad, no se superan; sirven para planificar con margen. La pérdida P80 (pinball) mide el error de q80 castigando más quedarse corto que pasarse; menor es mejor. coverage80 cuenta en cuántas semanas del backtest el real quedó bajo q80 (lo esperable es cerca de 80 %).
cubiertas, total = res.coverage80
print(f"bajo P80 en {cubiertas} de {total} semanas")
# con calibrate=True, cuánto se ensanchó cada banda (1 = nada)
cal =run_forecast(semanal,12,calibrate=True)
print({k: round(v,2)for k, v in cal.interval_scale.items()})
fit(history, target_col) aprende de la serie semanal. predict(horizon) devuelve horizon.length filas con timestamp y una columna por cuantil de horizon.quantiles (q50, q80, q90, q95; con el criterio WIS también q5, q10, q20), ordenadas. El constructor no debe exigir argumentos (o se registra una función que lo construya). Las fechas futuras salen de future_index.
import numpy as np
from urgencias_core.models.protocol import HorizonSpec, future_index
classUltimoAnio:
"""Cada semana = la misma semana del año pasado, ± su variación."""
Los modelos por nombre. default_models() son los que se miden por defecto: Ensamble, que pronostica, y SeasonalNaive, AutoARIMA, Armónico y MSTL como referencia; available_models() suma los opcionales; resolve_models acepta nombres sin tildes ni mayúsculas, o 'archivo:Clase' para uno propio.
names
lista de nombres; None = los de default_models()
Devuelve: dict nombre → fábrica (una instancia nueva por ajuste).
from urgencias_core import available_models, default_models
from urgencias_core.models.registry import resolve_models
Ajusta cada modelo desde cero en ventanas que van hacia atrás desde el final y guarda lo que predijo. scores() da una fila por ventana y modelo.
history
serie semanal
models
nombre → fábrica
length
semanas de cada ventana
origins, step
número de ventanas y semanas entre ellas
Devuelve:Backtest: windows, scores(), failed, pairs(modelo). scores() trae mae, la pérdida de cada cuantil (qloss_80, …), sus dos partes (qloss_80_short: semanas sobre el P80, a 0,8 por atención; qloss_80_excess: bajo él, a 0,2), qloss_mean (promedio de P50 a P95), wis (si se pidieron P5, P10 y P20), el ancho width_80 (P80 menos P50) y covered de n semanas bajo el P80. compare_scores hace la comparación de compare_models sobre una corrida ya hecha.
from urgencias_core import backtest
dos = {"Armónico": modelos["Armónico"], "UltimoAnio": UltimoAnio}
¿El candidato le gana a la base de forma consistente? Ajusta ambos en las mismas ventanas (36 de 4 semanas por defecto), cuenta en cuántas gana, aplica una prueba de signos y separa invierno del resto. Es urg-forecast comparar.
history
serie semanal
base, candidate
pares (nombre, fábrica)
horizon_weeks, origins, step
ventanas (4, 36, 4)
metric
qué se compara en cada ventana (por defecto "qloss_80")
Devuelve:Comparison: verdict (mejora, empeora, sin diferencia clara), text(), summary(), windows.
from urgencias_core import compare_models
from urgencias_core.models.harmonic import HarmonicRegression
UltimoAnio frente a Armónico, 8 ventanas de 4 semanas: gana 3, pierde 5 (p = 0.73); cambio mediano de la pérdida P80 +22.7 %. Veredicto: sin diferencia clara.
Regresores
Variables externas al DEIS (feriados, virus, clima) con las reglas de su fuente. Explicación y resultados en la página Regresores.
Una tabla semanal (timestamp + una columna por variable) y las reglas de su fuente: cuántas semanas tarda en publicarse y si su futuro se conoce. Vienen calendar() (feriados, interferiados, vacaciones escolares; futuro conocido) y flunet() (positividad de influenza y VRS; 2 semanas de atraso).
El Armónico más un regresor. En cada ventana solo usa lo que estaba publicado en esa fecha; lo que falta lo rellena con el promedio histórico ("climatology") o con una proyección de la serie ("forecast"). regressor_path muestra qué supuso para las semanas pronosticadas.
regressor
un Regressor
columns
subconjunto de columnas (por defecto todas)
lag_weeks
la semana t usa el valor de t − rezago
future
"climatology" o "forecast"
Devuelve: un modelo que cumple el contrato Forecaster.
from urgencias_core.models.exogenous import HarmonicExogenous
Recetas paso a paso para sumar algo propio y medir si sirve. Dónde va cada pieza está en Arquitectura.
Agregar tu propio modelo
Un modelo es una clase con dos métodos:
fit(history, target_col): recibe la historia semanal (un DataFrame con
timestamp y la columna target_col) y aprende lo que necesite.
predict(horizon): devuelve un DataFrame con una fila por semana futura y las
columnas timestamp y una por cada cuantil de horizon.quantiles: q50, q80,
q90 y q95, más q5, q10 y q20 cuando se elige con --criterio wis.
horizon.length es la cantidad de semanas.
El constructor no debe exigir argumentos.
1. Escribe el modelo. Este ejemplo pronostica cada semana como el promedio
de esa misma semana en los últimos tres años, y arma los intervalos con los
errores que esa regla tuvo en el pasado. Guárdalo como mi_modelo.py en la
carpeta donde vas a correr el comando:
mi_modelo.py
import numpy as np
import pandas as pd
from urgencias_core.models.protocol import future_index
classPromedioAnual:
"""Cada semana futura = promedio de esa misma semana en los últimos años."""
def__init__(self, años=3):
self.años = años
deffit(self, history, target_col):
s = history.set_index("timestamp")[target_col].astype(float)
self.ultima_semana = s.index[-1]
# Promedio de cada semana del año (1 a 53), solo con los últimos años.
Acá la regla simple pierde: no sigue los cambios de nivel recientes. Ese es el
punto de comparar antes de confiar en un modelo. Si el tuyo gana de forma
consistente en tu establecimiento, úsalo solo con -m mi_modelo:PromedioAnual.
Desde Python es lo mismo: agrega tu clase a los modelos por defecto. Su backtest
aparece junto al de los demás; el pronóstico sigue siendo de Ensamble, salvo que pidas
elegir con un criterio.
elegido =run_forecast(semanal,12,models=modelos,select_by="qloss_80") # gana el mejor
Más ejemplos en src/urgencias_core/models/: harmonic.py (regresión con
términos de Fourier y feriados) y ensemble.py (combina varios modelos).
Agregar un regresor externo
Un regresor es una serie semanal que no viene del DEIS: feriados, circulación viral,
temperatura, contaminación, vacunación. La forma estándar de sumarlo tiene dos pasos:
agregarlo sin hacer trampa y medir si sirve. Qué son, cuáles vienen y qué
mostraron con datos reales está en
docs/regresores.md.
En la demo puedes agregarlos al
pronóstico con un botón.
1. Agregarlo. Un Regressor es una tabla con timestamp (el lunes de cierre de cada
semana DEIS) y una columna por variable, más las reglas de su fuente. Vienen dos:
flunet() (positividad viral, 2 semanas de atraso) y calendar() (feriados,
interferiados y vacaciones escolares, que se conocen de antemano). Uno propio se declara
igual, y HarmonicExogenous.from_regressor lo suma al Armónico:
import pandas as pd
from urgencias_core.models.exogenous import HarmonicExogenous
lag_weeks=0,# la semana t usa el valor de la semana t - lag
future="forecast",# qué hacer con lo no publicado: "forecast" o "climatology"
)
La regla que lo mantiene honesto: en cada ventana del backtest el modelo solo ve los
datos que ya estaban publicados en esa fecha. Lo que falta se rellena con el promedio
histórico de esa semana del año ("climatology") o con una proyección de la propia serie
("forecast": Armónico sin tendencia y ARIMA, que arrastra si la temporada viene
adelantada o atrasada). 2020 y 2021 quedan fuera de ambos. Las variables con futuro
conocido (known_future=True, como el calendario) se usan tal cual, también para las
semanas que se pronostican.
2. Medir si sirve. Tres ventanas alcanzan para elegir modelo, no para saber si un
regresor ayuda: con pocas, la diferencia es casi siempre ruido. compare_models ajusta
ambos modelos en las mismas 36 ventanas de 4 semanas (unos tres inviernos), cuenta en
cuántas gana el candidato, aplica una prueba de signos y separa invierno del resto:
from urgencias_core.eval.compare import compare_models
from urgencias_core.models.harmonic import HarmonicRegression
print(cmp.text()) # gana, pierde, p, cambio mediano y veredicto
cmp.summary() # todas, invierno (mayo a septiembre) y resto
cmp.windows # una fila por ventana
Desde la terminal, con un modelo incluido o uno propio (archivo:Clase):
Ventana de terminal
urg-forecastcomparar24-105-mArmonicoFluNetProy
El veredicto es mejora, empeora o sin diferencia clara, por establecimiento. Si
pruebas muchos, cerca de uno de cada veinte saldrá distinto de “sin diferencia” por azar:
un regresor útil mejora en muchos, no en unos pocos. El ejemplo completo, con FluNet y el
calendario, está en examples/04_regresor_externo.py.
Pedirle a una IA que lo extienda
Si usas un asistente de IA (ChatGPT, Claude, Copilot u otro), copia esta
instrucción, reemplaza lo que está entre corchetes y pégala. Le da el contexto y
las reglas que necesita para que el modelo funcione con urg-forecast:
Estoy usando urg-forecast-core, un paquete de Python para pronosticar las
atenciones semanales de un servicio de urgencia en Chile con datos públicos del
DEIS MINSAL (https://github.com/nicoveraz/urg-forecast-core).
Revisa lo que te entregue igual que cualquier modelo: lo que importa es la
tabla de backtest, no la explicación.
Otras ideas
Otras series. Con load_deis(..., source="deis") (los archivos completos del
DEIS) tienes conteos diarios por causa y grupo de edad, así que puedes analizar y
pronosticar las causas respiratorias o la urgencia pediátrica en vez del total. La copia
semanal del repositorio trae solo el total.
Fuentes externas. Con la receta de Agregar un regresor externo
se puede probar clima, vacunación o vigilancia regional con el mismo rigor. Los dos
ejemplos incluidos dan resultados opuestos (detalle en docs/modelos.md): los feriados
mejoran el pronóstico en la mayoría de los 40 hospitales con más atenciones
(ArmónicoFeriados), mientras que la circulación viral de FluNet no mejora el total de
atenciones en ninguno de forma consistente. Las dos cosas son resultados.
Calendario chileno.urgencias_core.features.calendar_features (por día) y
weekly_calendar (por semana DEIS) construyen variables de feriados, interferiados,
calendario escolar y eventos regionales; regressors.calendar() las deja listas para
HarmonicExogenous.
Revisa docs/roadmap.md
para ver brechas conocidas que sirven como primeras contribuciones.
Generada con scripts/construir_api.py y urg-forecast-core 0.4.0; las recetas vienen de la sección "Extender" del README. La CI ejecuta todos los ejemplos y falla si una firma cambia sin regenerar la página.