API Reference¶
Esta página documenta la API pública del paquete estadistica_ambiental. La documentación se
genera automáticamente a partir de los docstrings con mkdocstrings.
Solo se documentan las funciones y clases con docstrings públicos. Los módulos internos (
__pycache__, helpers privados con_inicial) se omiten.
I/O¶
io.connectors¶
connectors ¶
Conectores a fuentes de datos ambientales colombianas públicas.
Provee acceso estandarizado a APIs y portales de datos abiertos usados en las 17 líneas temáticas. Cada función devuelve un DataFrame con columnas normalizadas compatibles con el pipeline del repositorio.
Fuentes incluidas: - OpenAQ: calidad del aire (PM2.5, PM10, O3, NO2, SO2, CO) - RMCAB: Red de Monitoreo de Calidad del Aire de Bogotá - SIATA: Sistema de Alerta Temprana de Medellín/Antioquia - IDEAM DHIME: datos hidrometeorológicos (instrucciones de acceso manual) - SMByC: alertas de deforestación IDEAM (instrucciones de acceso)
list_datasets_co ¶
Busca datasets en datos.gov.co relacionados con el query ambiental.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
str
|
Término de búsqueda (ej. 'calidad agua', 'deforestacion', 'caudal'). |
'calidad aire'
|
limit
|
int
|
Número máximo de resultados. |
10
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame con name, description, url, organization, updated (epoch, |
DataFrame
|
último refresco de datos) y created (epoch, fecha de alta del dataset |
DataFrame
|
en el portal — la señal correcta para detectar fuentes nuevas). |
load_datos_gov_co_dataset ¶
load_datos_gov_co_dataset(dataset_id: str, where: Optional[str] = None, select: Optional[str] = None, limit: int = 50000, app_token: Optional[str] = None) -> pd.DataFrame
Descarga filas de un dataset SODA en datos.gov.co.
Cliente genérico de la Socrata Open Data API (SODA). A diferencia de
list_datasets_co (que solo lista metadatos), esta función descarga las
filas reales del dataset identificado por dataset_id (p. ej.
"7g8z-fpvn"). El endpoint usado es:
https://www.datos.gov.co/resource/<dataset_id>.json.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataset_id
|
str
|
ID del dataset (parte después de |
required |
where
|
Optional[str]
|
Cláusula SoQL |
None
|
select
|
Optional[str]
|
Cláusula SoQL |
None
|
limit
|
int
|
Tope total de filas a descargar (paginación interna por 50000). |
50000
|
app_token
|
Optional[str]
|
Token opcional |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
DataFrame
|
DataFrame con las columnas tal como las devuelve el dataset (sin |
|
normalización |
DataFrame
|
los datasets son heterogéneos). |
Notas
El endpoint SODA pagina con $offset y un máximo de 50000 filas por
consulta. Esta función itera hasta alcanzar limit o agotar resultados.
load_ideam_dhime ¶
load_ideam_dhime(path: str, date_col: str = 'Fecha', value_col: Optional[str] = None, station_col: Optional[str] = None, variable: Optional[str] = None) -> pd.DataFrame
Carga datos de IDEAM DHIME desde archivo descargado manualmente.
El portal DHIME no tiene API pública. Los datos deben descargarse en: http://dhime.ideam.gov.co/atencionciudadano/
Pasos
- Registrarse en el portal (gratuito).
- Buscar la estación por código, nombre o municipio.
- Seleccionar variable (precipitación, temperatura, caudal, etc.)
- Descargar en formato Excel o CSV.
- Cargar con esta función.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Ruta al archivo XLSX o CSV descargado. |
required |
date_col
|
str
|
Nombre de la columna de fechas en el archivo DHIME. |
'Fecha'
|
value_col
|
Optional[str]
|
Nombre de la columna del valor. Si None, infiere automáticamente. |
None
|
station_col
|
Optional[str]
|
Nombre de la columna de estación. |
None
|
variable
|
Optional[str]
|
Nombre descriptivo de la variable (para documentar). |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame con columnas: fecha, estacion, variable, valor. |
load_ideam_dhime_csv ¶
load_ideam_dhime_csv(path: str, parametro: str, fecha_col_candidates: Optional[list[str]] = None) -> pd.DataFrame
Lee CSV de IDEAM DHIME con líneas de metadatos previas al encabezado.
Variante robusta de load_ideam_dhime específica para los CSV exportados
por DHIME, que típicamente traen varias filas de metadatos (estación,
municipio, coordenadas, etc.) antes del encabezado real, y nombran la
columna de valor de forma localizada (VALOR, Valor [mm],
valor_observado...).
La función inspecciona las primeras líneas hasta detectar una fila que
contenga alguno de los candidatos de fecha y, a partir de ahí, parsea el
CSV. Luego identifica la columna de valor por: (a) coincidencia con el
parametro solicitado en el nombre o (b) primera columna numérica.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Ruta al CSV exportado desde DHIME. |
required |
parametro
|
str
|
Nombre descriptivo del parámetro ( |
required |
fecha_col_candidates
|
Optional[list[str]]
|
Nombres alternativos para la columna de fecha.
Default: |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame con columnas: |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
Si |
load_openaq ¶
load_openaq(location_id: Optional[int] = None, location_name: Optional[str] = None, country: str = 'CO', parameter: str = 'pm25', date_from: Optional[str] = None, date_to: Optional[str] = None, limit: int = 10000) -> pd.DataFrame
Descarga mediciones de calidad del aire desde OpenAQ v3.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
location_id
|
Optional[int]
|
ID numérico de la estación en OpenAQ (preferido). |
None
|
location_name
|
Optional[str]
|
Sin soporte del lado servidor -- la API v3 de OpenAQ
no ofrece un parámetro de búsqueda de estaciones por nombre
(solo coordenadas/radio, país o ID). Pasar este parámetro sin
|
None
|
country
|
str
|
Código ISO de país. Solo aplica (y solo se valida) cuando
no se pasa |
'CO'
|
parameter
|
str
|
Variable a descargar ('pm25', 'pm10', 'o3', 'no2', 'so2', 'co'). |
'pm25'
|
date_from
|
Optional[str]
|
Fecha inicio 'YYYY-MM-DD' (default: últimos 30 días). |
None
|
date_to
|
Optional[str]
|
Fecha fin 'YYYY-MM-DD' (default: hoy). |
None
|
limit
|
int
|
Máximo de registros por consulta. |
10000
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame con columnas: fecha, estacion, parametro, valor, unidad, lat, lon. |
Ejemplos de location_id para Colombia (OpenAQ): - 225433 → Estación Kennedy, RMCAB Bogotá - 64510 → Estación El Poblado, SIATA Medellín Buscar IDs en: https://explore.openaq.org/
load_rmcab ¶
load_rmcab(station: str, variable: str = 'PM25', date_from: str = '2024-01-01', date_to: Optional[str] = None, token: Optional[str] = None) -> pd.DataFrame
Descarga datos de calidad del aire desde RMCAB Bogotá.
Requiere token gratuito de la Secretaría Distrital de Ambiente (SDA). Solicitar en: http://rmcab.ambientebogota.gov.co/
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station
|
str
|
Código de la estación (ej. 'Kennedy', 'Usme', 'Fontibon'). |
required |
variable
|
str
|
Variable ('PM25', 'PM10', 'O3', 'NO2', 'SO2', 'CO'). |
'PM25'
|
date_from
|
str
|
Fecha inicio 'YYYY-MM-DD'. |
'2024-01-01'
|
date_to
|
Optional[str]
|
Fecha fin (default: hoy). |
None
|
token
|
Optional[str]
|
Token de acceso SDA. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame con columnas: fecha, estacion, variable, valor, unidad. |
Nota
Sin token, los datos pueden consultarse manualmente en: http://rmcab.ambientebogota.gov.co/Report/stationreport
load_siata_aire ¶
Carga datos de calidad del aire de SIATA (Medellín/Antioquia).
Puede cargar desde archivo local (descarga previa) o intentar descargar desde datos.gov.co. Dado que la URL puede cambiar, se recomienda descarga manual.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Optional[str]
|
Ruta al CSV descargado desde datos.gov.co o portal SIATA. |
None
|
variable
|
str
|
Variable a filtrar en la columna 'variable' o 'parametro'. |
'PM2.5'
|
Portales de descarga
- https://www.datos.gov.co/ (buscar "SIATA calidad aire")
- https://siata.gov.co/siata_nuevo/index.php/descargaData
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame con columnas: fecha, estacion, variable, valor, unidad, lat, lon. |
load_sisaire ¶
load_sisaire(estacion: Optional[str], parametro: str = 'PM2.5', fecha_ini: str = '2024-01-01', fecha_fin: Optional[str] = None, timeout: float = 30.0) -> pd.DataFrame
Descarga CSV de SISAIRE (IDEAM) con fallback de encoding utf-8 → latin-1.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
estacion
|
Optional[str]
|
Código o nombre de estación SISAIRE; |
required |
parametro
|
str
|
Variable a descargar (PM2.5, PM10, O3, NO2, SO2, CO). |
'PM2.5'
|
fecha_ini
|
str
|
Fecha inicio |
'2024-01-01'
|
fecha_fin
|
Optional[str]
|
Fecha fin |
None
|
timeout
|
float
|
Timeout HTTP en segundos. |
30.0
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame con columnas normalizadas según |
DataFrame
|
(p. ej. |
Notas
El portal SISAIRE entrega CSV usualmente codificados en latin-1; esta
función intenta primero utf-8 y, si falla con UnicodeDecodeError,
reintenta con latin-1 para evitar mojibake (U+FFFD).
load_sisaire_local ¶
load_sisaire_local(anios: int | list[int] | None = None, parametro: str = 'pm25', estaciones: list[str] | None = None, path: 'str | None' = None) -> pd.DataFrame
Lee descargas SISAIRE locales (CAR_<año>.csv) sin duplicar archivos.
Pensado para uso con datos descargados manualmente del portal SISAIRE / CAR
(formato: "Estacion","Fecha inicial","Fecha final","PM2.5"). La carpeta
se referencia por config.SISAIRE_LOCAL_DIR (variable de entorno
SISAIRE_LOCAL_DIR); el repo nunca asume una ruta fija.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
anios
|
int | list[int] | None
|
Año (int), lista de años o |
None
|
parametro
|
str
|
Variable normalizada esperada ( |
'pm25'
|
estaciones
|
list[str] | None
|
Si se pasa, filtra |
None
|
path
|
'str | None'
|
Carpeta explícita. Si es |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame con columnas |
DataFrame
|
la columna del parámetro como float (p. ej. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
Si no se configuró |
load_smbyc_alertas ¶
Carga alertas tempranas de deforestación del SMByC desde archivo local.
El SMByC publica alertas trimestrales como Shapefile o GeoJSON en: http://smbyc.ideam.gov.co/MonitoreoBC-WEB/reg/indexLogOn.jsp
También disponibles en el portal SIAC: http://www.siac.gov.co/
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Ruta al Shapefile (.shp) o GeoJSON descargado del SMByC. |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
GeoDataFrame (si geopandas disponible) o DataFrame con columnas: |
DataFrame
|
fecha_alerta, area_ha, municipio, departamento, geometry (si aplica). |
io.loaders¶
loaders ¶
Ingesta multiformato para datos ambientales. Soporta: CSV, Excel, Parquet, NetCDF, Shapefile / GeoPackage / GeoJSON.
load ¶
Carga un archivo ambiental detectando el formato por extensión.
Para Shapefile / GeoPackage / GeoJSON devuelve un GeoDataFrame (requiere geopandas). Para el resto, un DataFrame de pandas.
load_csv ¶
load_csv(path: Union[str, Path], date_col: Optional[str] = None, sep: str = ',', encoding: Optional[str] = None, **kwargs) -> pd.DataFrame
Carga CSV con detección automática de encoding si no se especifica.
load_excel ¶
load_excel(path: Union[str, Path], date_col: Optional[str] = None, sheet_name: Union[str, int] = 0, **kwargs) -> pd.DataFrame
Carga archivo Excel (.xlsx / .xls).
load_netcdf ¶
load_netcdf(path: Union[str, Path], variable: Optional[str] = None, date_col: str = 'time', lat_col: str = 'lat', lon_col: str = 'lon', **kwargs) -> pd.DataFrame
Carga NetCDF y aplana a DataFrame de pandas.
Si variable es None, carga todas las variables del archivo.
Requiere: netCDF4 o h5netcdf (instalar con pip install netcdf4).
load_parquet ¶
Carga archivo Parquet.
load_shapefile ¶
Carga Shapefile, GeoPackage o GeoJSON a GeoDataFrame.
Requiere: geopandas (pip install geopandas).
io.validators¶
validators ¶
Validación de plausibilidad física y calidad de datos ambientales.
Detecta: duplicados, rangos físicos imposibles, fechas inconsistentes, coordenadas fuera de área de estudio. No lanza excepciones — devuelve un ValidationReport con todos los hallazgos para que el analista decida.
validate ¶
validate(df: DataFrame, date_col: Optional[str] = None, key_cols: Optional[List[str]] = None, ranges: Optional[Dict[str, Tuple[float, float]]] = None, colombia_coords: bool = True, linea_tematica: Optional[str] = None) -> ValidationReport
Valida un DataFrame ambiental y devuelve un reporte con todos los hallazgos.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
DataFrame a validar. |
required |
date_col
|
Optional[str]
|
Nombre de la columna de fechas. |
None
|
key_cols
|
Optional[List[str]]
|
Columnas que forman la llave lógica (e.g. ['estacion', 'fecha']). |
None
|
ranges
|
Optional[Dict[str, Tuple[float, float]]]
|
Rangos personalizados {col: (min, max)} que sobreescriben los defaults. |
None
|
colombia_coords
|
bool
|
Si True, valida latitud/longitud en el bounding box de Colombia. |
True
|
linea_tematica
|
Optional[str]
|
Nombre de la línea temática ('paramos', 'calidad_aire', 'oferta_hidrica', 'recurso_hidrico', 'humedales'). Aplica rangos específicos de dominio sobre los rangos base. |
None
|
EDA¶
eda.profiling¶
profiling ¶
Reporte automático de EDA para datasets ambientales.
Genera un HTML autocontenido que integra
- Catálogo de variables (variables.py)
- Análisis de calidad (quality.py)
- Validación de rangos físicos (validators.py)
- Estadísticas descriptivas básicas
Integración opcional con ydata-profiling o sweetviz cuando están instalados.
run_eda ¶
run_eda(df: DataFrame, output: str = 'reports/eda_report.html', title: str = 'EDA Ambiental', date_col: Optional[str] = None, use_ydata: bool = True, use_sweetviz: bool = False) -> Path
Genera el reporte completo de EDA y lo guarda en disco.
Siempre produce el reporte propio. Si use_ydata=True y ydata-profiling está instalado, genera también el reporte completo de ydata en un archivo separado (
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
DataFrame ambiental. |
required |
output
|
str
|
Ruta del HTML de salida. |
'reports/eda_report.html'
|
title
|
str
|
Título del reporte. |
'EDA Ambiental'
|
date_col
|
Optional[str]
|
Columna de fechas para análisis temporal. |
None
|
use_ydata
|
bool
|
Intentar generar reporte ydata-profiling si está disponible. |
True
|
use_sweetviz
|
bool
|
Intentar generar reporte sweetviz si está disponible. |
False
|
Returns:
| Type | Description |
|---|---|
Path
|
Path al HTML generado. |
eda.quality¶
quality ¶
Análisis profundo de calidad de datos para series ambientales.
Complementa io/validators.py (plausibilidad física) con análisis estadístico: patrones de faltantes, gaps temporales, congelamiento de sensor y outliers. No elimina ni imputa datos — solo diagnostica para informar la estrategia.
MissingPattern ¶
Bases: str, Enum
Clasificación heurística del mecanismo de datos faltantes.
assess_quality ¶
assess_quality(df: DataFrame, date_col: Optional[str] = None, numeric_cols: Optional[List[str]] = None, freeze_min_length: int = 5, cross_checks: bool = True) -> QualityReport
Análisis profundo de calidad para un DataFrame ambiental.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
DataFrame a analizar. |
required |
date_col
|
Optional[str]
|
Columna de fechas para análisis temporal. |
None
|
numeric_cols
|
Optional[List[str]]
|
Columnas numéricas a analizar (None = todas). |
None
|
freeze_min_length
|
int
|
Mínimo de registros iguales consecutivos para considerar congelamiento de sensor. |
5
|
cross_checks
|
bool
|
Si True, evalúa inconsistencias entre columnas (e.g., PM2.5 > PM10). |
True
|
eda.variables¶
variables ¶
Tipificación automática de variables en datasets ambientales.
Clasifica cada columna en: numérica continua, numérica discreta, categórica nominal, categórica ordinal, temporal, espacial o texto libre. Permite sobreescrituras manuales para casos que la heurística no resuelve.
VariableCatalog
dataclass
¶
Catálogo de variables tipificadas para un DataFrame ambiental.
classify ¶
Clasifica automáticamente las columnas de un DataFrame ambiental.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
DataFrame a tipificar. |
required |
overrides
|
Optional[Dict[str, VariableType]]
|
Mapa {columna: VariableType} para sobreescribir la heurística. Ejemplo: {"calidad_agua": VariableType.CATEGORICAL_ORDINAL} |
None
|
eda.viz¶
viz ¶
Visualizaciones estándar de EDA para datos ambientales.
Todas las funciones devuelven matplotlib Figure para que el caller decida si mostrar, guardar o incrustar en un notebook/reporte. No llaman plt.show() — control queda en el usuario.
plot_boxplot ¶
plot_boxplot(df: DataFrame, value_col: str, group_col: Optional[str] = None, title: Optional[str] = None, figsize: tuple = (8, 4)) -> plt.Figure
Boxplot por grupo o global.
plot_correlation_heatmap ¶
plot_correlation_heatmap(df: DataFrame, method: str = 'pearson', cols: Optional[List[str]] = None, figsize: tuple = (8, 7)) -> plt.Figure
Heatmap de correlaciones con anotaciones numéricas.
plot_histogram ¶
plot_histogram(df: DataFrame, col: str, bins: int = 30, group_col: Optional[str] = None, title: Optional[str] = None, figsize: tuple = (7, 4)) -> plt.Figure
Histograma con KDE superpuesta, opcional por grupo.
plot_missing_heatmap ¶
plot_missing_heatmap(df: DataFrame, date_col: Optional[str] = None, figsize: tuple = (12, 5)) -> plt.Figure
Mapa de calor de datos faltantes: filas=tiempo, columnas=variables.
plot_multi_series ¶
plot_multi_series(df: DataFrame, date_col: str, value_cols: Sequence[str], title: Optional[str] = None, figsize: tuple = (12, 3)) -> plt.Figure
Subplots independientes, uno por variable, compartiendo eje X.
plot_scatter ¶
plot_scatter(df: DataFrame, x_col: str, y_col: str, color_col: Optional[str] = None, title: Optional[str] = None, figsize: tuple = (6, 5)) -> plt.Figure
Scatter plot con línea de regresión y coloreado opcional por categoría.
plot_seasonal_means ¶
plot_seasonal_means(df: DataFrame, date_col: str, value_col: str, period: str = 'month', figsize: tuple = (10, 4)) -> plt.Figure
Promedio mensual o por día de semana para detectar estacionalidad.
plot_series ¶
plot_series(df: DataFrame, date_col: str, value_col: str, group_col: Optional[str] = None, title: Optional[str] = None, ylabel: Optional[str] = None, figsize: tuple = (12, 4)) -> plt.Figure
Serie temporal simple o por grupo (una línea por categoría).
Preprocesamiento¶
preprocessing.air_quality¶
air_quality ¶
Funciones específicas para preprocesamiento de calidad del aire.
Incluye
- Categorización ICA según Resolución 2254/2017 (Colombia)
- Detección de episodios contaminantes con validación espacial
- Corrección de sesgo estacional en modelos de pronóstico
Nota: ICA_CATEGORIES en config.py corresponde al Índice de Calidad del Agua (IDEAM, escala 0-1) y es distinto del ICA de calidad del aire de Res. 2254/2017.
categorize_ica ¶
categorize_ica(series: Series, pollutant: str = 'pm25', standard: str = 'res_2254_2017') -> pd.Series
Categoriza una serie de concentraciones según el ICA de Res. 2254/2017.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
series
|
Series
|
Serie de valores de concentración del contaminante. |
required |
pollutant
|
str
|
Contaminante. Opciones: 'pm25', 'pm10', 'o3', 'no2', 'so2', 'co'. Si no se reconoce, usa los breakpoints de PM2.5 con aviso. |
'pm25'
|
standard
|
str
|
Norma de referencia. Solo 'res_2254_2017' está implementada; el parámetro se reserva para versiones futuras (ej. estándar OMS). |
'res_2254_2017'
|
Returns:
| Type | Description |
|---|---|
Series
|
pd.Series de tipo Categorical con etiquetas: |
Series
|
"Buena", "Aceptable", "Dañina sensibles", "Dañina", "Muy dañina", "Peligrosa". |
Series
|
NaN donde la entrada sea NaN. |
Raises:
| Type | Description |
|---|---|
ValueError
|
Si |
Example
import pandas as pd from estadistica_ambiental.preprocessing.air_quality import categorize_ica s = pd.Series([8.0, 20.0, 40.0, 60.0, 160.0, 300.0]) categorize_ica(s, pollutant='pm25') 0 Buena 1 Aceptable 2 Dañina sensibles 3 Dañina 4 Muy dañina 5 Peligrosa dtype: category
correct_seasonal_bias ¶
correct_seasonal_bias(predictions: Series, actuals: Series, time_col: Series, by: Literal['month', 'quarter', 'week'] = 'month') -> Tuple[pd.Series, pd.DataFrame]
Calcula y aplica corrección de sesgo estacional a predicciones de modelo.
El sesgo sistemático ocurre cuando el modelo sobreestima o subestima de forma consistente en ciertos períodos (e.g., meses secos vs. lluviosos). Esta función calcula el sesgo promedio por período y lo descuenta:
predicción_corregida = predicción − sesgo_del_período
Un sesgo positivo (sobreestimación) resulta en corrección hacia abajo; un sesgo negativo (subestimación) eleva la predicción.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
predictions
|
Series
|
Serie de valores predichos por el modelo. |
required |
actuals
|
Series
|
Serie de valores reales observados (mismo índice que predictions). |
required |
time_col
|
Series
|
Serie de fechas/horas correspondiente a cada observación. Debe ser parseable como datetime. Mismo largo que predictions. |
required |
by
|
Literal['month', 'quarter', 'week']
|
Granularidad temporal del sesgo: - 'month' → sesgo por mes del año (1-12). - 'quarter' → sesgo por trimestre (1-4). - 'week' → sesgo por semana del año (1-53). |
'month'
|
Returns:
| Type | Description |
|---|---|
Series
|
Tupla |
DataFrame
|
|
Tuple[Series, DataFrame]
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
Si |
ValueError
|
Si |
Example
preds_ok, bias_df = correct_seasonal_bias( ... predictions=df["predicho"], ... actuals=df["real"], ... time_col=df["datetime"], ... by="month", ... ) bias_df.head() periodo sesgo n_obs sesgo_std 0 1 2.314 720 1.203 1 2 -0.891 672 0.987 ...
flag_spatial_episodes ¶
flag_spatial_episodes(df: DataFrame, value_col: str, station_col: str, datetime_col: str, lat_col: str, lon_col: str, iqr_multiplier: float = 3.0, min_consecutive_hours: int = 4, distance_km: float = 50.0, min_neighbor_stations: int = 1) -> pd.DataFrame
Detecta episodios contaminantes reales distinguiéndolos de errores de sensor.
Aplica un pipeline de tres pasos con trazabilidad completa (ADR-002):
1. Cap absoluto: valores > percentil 99.9 global se marcan 'cap_absoluto'.
2. Episodios críticos: secuencias ≥ min_consecutive_hours horas
consecutivas sobre IQR×iqr_multiplier, confirmadas por al menos
min_neighbor_stations estaciones vecinas (a ≤ distance_km km)
con elevación simultánea. Se marcan 'episodio_critico' y se PRESERVAN.
3. Outliers IQR por estación×mes: valores moderados (1.5×IQR) se marcan
'iqr_soft'; valores extremos (iqr_multiplier×IQR) no episódicos se
marcan 'iqr_hard'.
Los valores marcados como 'episodio_critico' NO se modifican: son eventos reales de contaminación que deben preservarse para análisis normativo.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
DataFrame con al menos las columnas indicadas en los parámetros. |
required |
value_col
|
str
|
Columna con la concentración del contaminante. |
required |
station_col
|
str
|
Columna identificadora de estación. |
required |
datetime_col
|
str
|
Columna de fecha/hora (dtype datetime o parseable). |
required |
lat_col
|
str
|
Columna de latitud de la estación (decimal, WGS-84). |
required |
lon_col
|
str
|
Columna de longitud de la estación (decimal, WGS-84). |
required |
iqr_multiplier
|
float
|
Multiplicador IQR para umbral extremo. Default 3.0. |
3.0
|
min_consecutive_hours
|
int
|
Mínimo de horas consecutivas para episodio crítico. Default 4. |
4
|
distance_km
|
float
|
Radio máximo (km) para considerar estaciones vecinas. Default 50. |
50.0
|
min_neighbor_stations
|
int
|
Mínimo de vecinas con elevación simultánea para confirmar episodio. Default 1. Si una estación no tiene vecinas, el criterio temporal es suficiente. |
1
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
Copia del DataFrame con columna adicional |
DataFrame
|
{'original', 'iqr_soft', 'iqr_hard', 'episodio_critico', 'cap_absoluto'}. |
Raises:
| Type | Description |
|---|---|
KeyError
|
Si alguna de las columnas requeridas no existe en |
Notes
- Requiere pandas y numpy. No requiere geopandas.
- El cálculo IQR se realiza por combinación estación×mes para capturar estacionalidad. Se requieren al menos 10 observaciones por grupo.
- La detección de horas consecutivas usa un umbral de 1.5 h de brecha para tolerar datos faltantes aislados.
preprocessing.imputation¶
imputation ¶
Imputación de datos faltantes para series ambientales.
Estrategias ordenadas de menor a mayor complejidad
forward_fill → linear → mean/median → rolling_mean → kalman → mice
impute ¶
impute(df: DataFrame, cols: Optional[List[str]] = None, method: str = 'linear', **kwargs) -> pd.DataFrame
Aplica el método de imputación seleccionado a las columnas numéricas.
Métodos disponibles
'ffill' Forward fill (última observación conocida). 'bfill' Backward fill. 'linear' Interpolación lineal temporal. 'mean' Reemplaza por media de la columna. 'median' Reemplaza por mediana de la columna. 'rolling_mean' Media rodante (window kwarg, default=24). 'kalman' Filtro de Kalman simple (requiere pykalman). 'mice' Imputación múltiple (requiere scikit-learn).
preprocessing.outliers¶
outliers ¶
Detección y tratamiento OPCIONAL de outliers en series ambientales.
Por defecto solo detecta y marca (ADR-002): los picos ambientales son señal real. El clipping es opt-in explícito con treat=True.
Funciones
- flag_outliers: detección puntual univariada (IQR / z-score / modified z-score).
- detect_regional_episodes: episodios sostenidos con confirmación espacial entre estaciones vecinas. Variante genérica de la lógica de calidad del aire, aplicable a cualquier variable ambiental (PM2.5, caudal, temperatura, etc.).
detect_regional_episodes ¶
detect_regional_episodes(df: DataFrame, value_col: str, station_col: str, datetime_col: str, lat_col: str, lon_col: str, iqr_hard_mult: float = 3.0, iqr_soft_mult: float = 1.5, min_duration_hours: int = 4, neighbor_radius_km: float = 50.0, min_neighbors_confirmed: int = 1, max_gap_hours: float = 1.5) -> pd.DataFrame
Detecta episodios regionales sostenidos con confirmación espacial.
Algoritmo (variante genérica de flag_spatial_episodes para cualquier
variable ambiental, validado en producción CAR §3.1.A):
- Por estación: calcular Q1, Q3, IQR sobre los valores no-NaN.
- Marcar como candidatos los puntos > Q3 +
iqr_hard_mult× IQR. - Agrupar candidatos consecutivos en episodios (brecha máxima
max_gap_hours) y descartar episodios con duración <min_duration_hours. - Para cada episodio sobreviviente, validar contra estaciones vecinas
dentro de
neighbor_radius_km(Haversine): se requieren al menosmin_neighbors_confirmedvecinos con valor > Q3_vecino +iqr_soft_mult× IQR en la misma ventana temporal. - Episodios confirmados →
flag_episode = "regional"(señal real). Candidatos no confirmados →flag_episode = "puntual"(probable falla de sensor o variabilidad local).
A diferencia de flag_spatial_episodes (calidad del aire), esta función:
- NO modifica los valores (no imputa, no recorta).
- NO aplica cap absoluto (eso es decisión opt-in del usuario).
- NO segmenta por mes (asume estacionariedad por estación).
- Es genérica: aplica a PM2.5, caudal, temperatura, precipitación, etc.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
DataFrame con observaciones de múltiples estaciones. |
required |
value_col
|
str
|
Columna con la variable a evaluar. |
required |
station_col
|
str
|
Columna identificadora de estación. |
required |
datetime_col
|
str
|
Columna temporal (datetime o parseable). |
required |
lat_col
|
str
|
Latitud de la estación (decimal, WGS-84). |
required |
lon_col
|
str
|
Longitud de la estación (decimal, WGS-84). |
required |
iqr_hard_mult
|
float
|
Multiplicador IQR para umbral fuerte (default 3.0). |
3.0
|
iqr_soft_mult
|
float
|
Multiplicador IQR para confirmación en vecinos (default 1.5). |
1.5
|
min_duration_hours
|
int
|
Duración mínima del episodio en horas (default 4). |
4
|
neighbor_radius_km
|
float
|
Radio de búsqueda de vecinas en km (default 50). |
50.0
|
min_neighbors_confirmed
|
int
|
Vecinas mínimas con elevación simultánea para confirmar el episodio (default 1). Si una estación queda aislada (ningún vecino dentro del radio), el criterio temporal basta. |
1
|
max_gap_hours
|
float
|
Brecha máxima en horas para considerar candidatos como parte del mismo episodio (default 1.5 — tolera 1 dato faltante). |
1.5
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
Copia del DataFrame con columna adicional |
DataFrame
|
|
Raises:
| Type | Description |
|---|---|
KeyError
|
Si alguna columna requerida no existe en |
Example
df = pd.DataFrame({ ... "fecha": pd.date_range("2024-01-01", periods=10, freq="h").tolist() * 2, ... "estacion": ["A"] * 10 + ["B"] * 10, ... "lat": [4.6] * 10 + [4.65] * 10, ... "lon": [-74.1] * 10 + [-74.15] * 10, ... "pm25": [...] # con pico sostenido en ambas estaciones ... }) out = detect_regional_episodes(df, "pm25", "estacion", "fecha", "lat", "lon") out["flag_episode"].value_counts()
flag_outliers ¶
flag_outliers(df: DataFrame, cols: Optional[List[str]] = None, method: str = 'iqr', threshold: float = 1.5, treat: bool = False, treatment: str = 'clip') -> pd.DataFrame
Marca columnas con outliers. Opcionalmente los trata.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
DataFrame de entrada. |
required |
cols
|
Optional[List[str]]
|
Columnas a analizar (None = todas numéricas). |
None
|
method
|
str
|
'iqr' | 'zscore' | 'modified_zscore'. |
'iqr'
|
threshold
|
float
|
Multiplicador IQR o número de desviaciones. |
1.5
|
treat
|
bool
|
Si True aplica treatment (clip o nan). Default False (ADR-002). |
False
|
treatment
|
str
|
'clip' recorta a los límites | 'nan' reemplaza por NaN. |
'clip'
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame con columnas adicionales ' |
preprocessing.resampling¶
resampling ¶
Remuestreo y agregación temporal de series ambientales.
align_frequencies ¶
align_frequencies(dfs: List[DataFrame], date_cols: List[str], target_freq: str = 'D', agg: str = 'mean') -> List[pd.DataFrame]
Alinea múltiples DataFrames a la misma frecuencia temporal.
fill_missing_timestamps ¶
Inserta timestamps faltantes con NaN para hacer la serie regular.
resample ¶
resample(df: DataFrame, date_col: str, value_cols: Optional[List[str]] = None, freq: str = 'D', agg: Union[str, Dict[str, str]] = 'mean', min_count: int = 1) -> pd.DataFrame
Remuestrea a una frecuencia objetivo.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
DataFrame con serie temporal. |
required |
date_col
|
str
|
Columna de fechas. |
required |
value_cols
|
Optional[List[str]]
|
Columnas a agregar (None = todas numéricas). |
None
|
freq
|
str
|
Frecuencia destino (e.g. 'H', 'D', 'W', 'ME', 'YE'). |
'D'
|
agg
|
Union[str, Dict[str, str]]
|
Función de agregación ('mean', 'sum', 'max', 'min') o dict por columna {'pm25': 'mean', 'lluvia': 'sum'}. |
'mean'
|
min_count
|
int
|
Mínimo de observaciones válidas para producir resultado. |
1
|
Estadística descriptiva¶
descriptive.univariate¶
univariate ¶
Estadística descriptiva univariada para variables ambientales.
frequency_table ¶
Tabla de frecuencias para variable categórica u ordinal.
summarize ¶
summarize(df: DataFrame, cols: Optional[List[str]] = None, group_col: Optional[str] = None, percentiles: List[float] = [0.05, 0.25, 0.5, 0.75, 0.95]) -> pd.DataFrame
Resumen estadístico completo para columnas numéricas.
Incluye: n, media, mediana, moda, desv. estándar, varianza, CV, IQR, MAD, asimetría, curtosis, percentiles, min, max. Soporta agrupación por variable categórica (e.g. estación).
descriptive.bivariate¶
bivariate ¶
Estadística descriptiva bivariada para datos ambientales.
chi2_test ¶
Chi-cuadrado de independencia entre dos variables categóricas.
contingency_table ¶
contingency_table(df: DataFrame, col1: str, col2: str, normalize: Optional[str] = None) -> pd.DataFrame
Tabla de contingencia. normalize: None | 'index' | 'columns' | 'all'.
correlation_matrix ¶
correlation_matrix(df: DataFrame, cols: Optional[List[str]] = None, method: str = 'pearson') -> pd.DataFrame
Matriz de correlación con p-valores para columnas numéricas.
Returns DataFrame con MultiIndex (coef, pval) por par de variables.
correlation_table ¶
correlation_table(df: DataFrame, cols: Optional[List[str]] = None, method: str = 'pearson', min_abs_corr: float = 0.0) -> pd.DataFrame
Tabla larga con pares (var1, var2, corr, pval) — más legible que la matriz.
descriptive.temporal¶
temporal ¶
Estadística descriptiva temporal: STL, ACF, PACF, rolling stats.
acf_values ¶
Autocorrelación (ACF) hasta nlags.
decompose_stl ¶
Descomposición STL (Seasonal-Trend decomposition using LOESS).
Returns DataFrame con columnas: observed, trend, seasonal, residual.
pacf_values ¶
Autocorrelación parcial (PACF) hasta nlags.
rolling_stats ¶
rolling_stats(series: Series, window: int, stats: Tuple[str, ...] = ('mean', 'std')) -> pd.DataFrame
Estadísticas rodantes para detectar cambios de nivel o varianza.
seasonal_summary ¶
Agrega la serie por frecuencia (M=mensual, Y=anual, W=semanal).
Returns: media, mediana, std, min, max por período.
Inferencia¶
inference.distributions¶
distributions ¶
inference.hypothesis¶
hypothesis ¶
Pruebas de hipótesis paramétricas y no paramétricas.
anova ¶
ANOVA de una vía para múltiples grupos.
kruskalwallis ¶
Kruskal-Wallis — alternativa no paramétrica a ANOVA.
mannwhitney ¶
mannwhitney(df: DataFrame, value_col: str, group_col: str, groups: Optional[List] = None, alpha: float = 0.05) -> dict
Mann-Whitney U — alternativa no paramétrica al t-test.
ttest ¶
ttest(df: DataFrame, value_col: str, group_col: str, groups: Optional[List] = None, alpha: float = 0.05, equal_var: bool = False) -> dict
t-test de Welch (equal_var=False) o Student entre dos grupos.
inference.intervals¶
intervals ¶
Intervalos de confianza paramétricos y bootstrap, y análisis de excedencias normativas.
ci_bootstrap ¶
ci_bootstrap(series: Series, statistic: Callable, confidence: float = 0.95, n_boot: int = 2000, random_state: int = 42) -> Tuple[float, float]
IC bootstrap genérico para cualquier estadístico.
ci_mean ¶
IC paramétrico para la media (t de Student).
ci_median_bootstrap ¶
ci_median_bootstrap(series: Series, confidence: float = 0.95, n_boot: int = 2000, random_state: int = 42) -> Tuple[float, float]
IC bootstrap para la mediana (no paramétrico).
ci_quantile_bootstrap ¶
ci_quantile_bootstrap(series: Series, q: float = 0.95, confidence: float = 0.9, n_boot: int = 2000, random_state: int = 42) -> Tuple[float, float]
IC bootstrap para un cuantil arbitrario (útil para excedencias de norma).
exceedance_probability ¶
Probabilidad de excedencia de un umbral (e.g. norma ambiental).
Útil para PM2.5 vs norma OMS (15 µg/m³) o norma colombiana (37 µg/m³).
exceedance_report ¶
Genera un reporte de cumplimiento normativo para una variable ambiental colombiana.
Compara la serie contra todas las normas colombianas relevantes para esa variable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
series
|
Series
|
Serie de observaciones (ya deben estar en la unidad correcta). |
required |
variable
|
str
|
Nombre de la variable ('pm25', 'dbo5', 'ph', etc.). |
required |
frecuencia
|
str
|
Frecuencia de los datos ('1h', '24h', 'anual', etc.) — informativo. |
'24h'
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame con una fila por norma, columnas: |
DataFrame
|
norma, umbral, n_exceedances, pct_exceed, cumple, return_period_days. |
ruido_exceedance_report ¶
Reporte de cumplimiento de ruido ambiental contra la Tabla 2 (Res. 627/2006).
Calcula L_Aeq (Art. 4) por día y ventana horaria (diurna/nocturna, Art. 2)
y lo compara contra el estándar máximo permisible del sector (Tabla 2,
Art. 17). Requiere una serie con DatetimeIndex -- sin fecha/hora no
se puede determinar la ventana horaria aplicable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
series
|
Series
|
Mediciones de nivel de presión sonora en dB(A), indexadas por fecha/hora (idealmente sub-horarias; con menos resolución el L_Aeq calculado es una aproximación). |
required |
sector
|
str
|
Uno de los sectores de la Tabla 2 -- ver |
required |
natural_noise
|
bool
|
Si |
False
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame con una fila por (día de ruido, horario): dia_ruido, |
DataFrame
|
horario, sector, l_aeq_dba, umbral_dba, excede, margen_db, |
DataFrame
|
n_mediciones (cantidad de lecturas agregadas en esa ventana -- |
DataFrame
|
una ventana con pocas mediciones es una aproximación pobre del |
DataFrame
|
L_Aeq,T real, ver Art. 4), nota. |
inference.stationarity¶
stationarity ¶
Pruebas de estacionariedad para series ambientales.
ADF y KPSS son obligatorias antes de aplicar ARIMA (ADR-004).
adf_test ¶
Augmented Dickey-Fuller.
H0: la serie tiene raíz unitaria (no estacionaria). Rechazar H0 → estacionaria.
kpss_test ¶
KPSS (Kwiatkowski-Phillips-Schmidt-Shin).
H0: la serie ES estacionaria. Rechazar H0 → no estacionaria.
stationarity_report ¶
Ejecuta ADF + KPSS y devuelve diagnóstico consolidado.
Interpretación conjunta (tabla de Hylleberg-Mizon): ADF no rechaza H0 + KPSS rechaza H0 → claramente no estacionaria ADF rechaza H0 + KPSS no rechaza H0 → claramente estacionaria Ambos rechazados / ninguno rechazado → evidencia mixta
inference.trend¶
trend ¶
Detección de tendencia en series ambientales.
Mann-Kendall + Sen's slope son el estándar en hidrología y calidad del aire para series largas con distribución no normal.
Modelos predictivos¶
predictive.base¶
base ¶
Clase base abstracta y protocolo ModelSpec para todos los modelos predictivos ambientales.
BaseModel ¶
Bases: ABC
Interfaz común para todos los modelos del catálogo.
Subclases deben implementar :meth:fit y :meth:predict.
Para participar en el pipeline de optimización bayesiana, las subclases
también pueden implementar el protocolo :class:ModelSpec añadiendo
:attr:warm_starts, :meth:suggest_params y :meth:build_model.
fit
abstractmethod
¶
Ajusta el modelo a la serie objetivo y exógenas opcionales.
fit_predict ¶
fit_predict(y: Series, horizon: int, X: Optional[DataFrame] = None, X_future: Optional[DataFrame] = None) -> np.ndarray
Ajusta el modelo y genera el pronóstico en un solo paso.
predict
abstractmethod
¶
Genera pronóstico para horizon pasos adelante.
ModelSpec ¶
Bases: Protocol
Protocolo estructural que todo modelo optimizable debe satisfacer.
Permite agregar nuevos modelos al pipeline de optimización sin modificar el optimizador. Basta con que la clase implemente los miembros requeridos; no es necesario heredar de esta clase (duck-typing estructural).
Uso típico::
class MiModelo:
name = "MiModelo"
@property
def warm_starts(self) -> list[dict]:
return [{"n_estimators": 100, "max_depth": 5}]
def suggest_params(self, trial) -> dict:
return {"n_estimators": trial.suggest_int("n_estimators", 50, 500)}
def build_model(self, params: dict):
return MiEstimador(**params)
assert isinstance(MiModelo(), ModelSpec) # True sin herencia
search_space
property
¶
Descripción del espacio de búsqueda (opcional, para documentación).
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Dict con metadatos del espacio: nombre → (tipo, min, max, ...). |
warm_starts
property
¶
Configuraciones iniciales conocidas para acelerar Optuna.
Cada dict se encola como trial inicial antes de la búsqueda aleatoria, reduciendo el número de evaluaciones necesarias para converger.
Returns:
| Type | Description |
|---|---|
List[Dict[str, Any]]
|
Lista de dicts con hiperparámetros (puede estar vacía). |
build_model ¶
Construye e instancia el modelo con los parámetros dados.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
Dict[str, Any]
|
Dict de hiperparámetros, típicamente obtenido de
:meth: |
required |
Returns:
| Type | Description |
|---|---|
Any
|
Instancia del modelo (sklearn, statsmodels, etc.) lista para |
Any
|
ser ajustada con |
suggest_params ¶
Sugiere hiperparámetros a partir de un Trial de Optuna.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trial
|
Any
|
|
required |
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Dict con los hiperparámetros sugeridos para este trial. |
OptimizationResult
dataclass
¶
OptimizationResult(best_params: Dict[str, Any], best_score: float, n_trials: int, model: Any = None, study: Any = None, model_name: str = '', cv_scores: List[float] = list(), fallback: bool = False)
Resultado estándar de una corrida de optimización bayesiana.
Attributes:
| Name | Type | Description |
|---|---|---|
best_params |
Dict[str, Any]
|
Mejores hiperparámetros encontrados por Optuna. |
best_score |
float
|
Valor de la métrica objetivo para |
n_trials |
int
|
Número de trials ejecutados. |
model |
Any
|
Instancia del modelo construida con |
study |
Any
|
Objeto |
model_name |
str
|
Nombre identificador del modelo optimizado. |
cv_scores |
List[float]
|
Puntuaciones individuales por trial (para análisis). |
fallback |
bool
|
True si Optuna falló y se usó el primer warm_start. |
predictive.classical¶
classical ¶
Modelos estadísticos clásicos: ARIMA, SARIMA, SARIMAX, ETS/Holt-Winters. Adaptado de boa-sarima-forecaster/model.py por Dan Méndez — 2026-04-22
Cambios respecto al original: - Interfaz BaseModel unificada (fit/predict). - Soporte SARIMAX con exógenas meteorológicas (crítico para calidad del aire). - Validación de estacionariedad obligatoria via stationarity.py (ADR-004). - Sin terminología financiera (SKU/country → variable/estacion).
ARIMAModel ¶
Bases: SARIMAXModel
ARIMA puro (sin estacionalidad ni exógenas).
warm_starts
property
¶
Configuraciones ARIMA iniciales (sin componentes estacionales) para Optuna.
ETSModel ¶
SARIMAModel ¶
SARIMAModel(order: Tuple[int, int, int] = (1, 1, 1), seasonal_order: Tuple[int, int, int, int] = (1, 1, 1, 12))
Bases: SARIMAXModel
SARIMA sin exógenas.
warm_starts
property
¶
Configuraciones SARIMA iniciales (con estacionalidad) para Optuna.
SARIMAXModel ¶
SARIMAXModel(order: Tuple[int, int, int] = (1, 1, 1), seasonal_order: Tuple[int, int, int, int] = (0, 0, 0, 0), trend: str = 'n', enforce_stationarity: bool = False, enforce_invertibility: bool = False)
Bases: BaseModel
SARIMAX — SARIMA con regresores exógenos opcionales.
Envuelve statsmodels.tsa.statespace.sarimax.SARIMAX con la interfaz BaseModel.
predictive.ml¶
ml ¶
Modelos de Machine Learning: XGBoost, Random Forest, LightGBM, SVR.
Todos usan features de lags internamente (feature engineering mínimo).
predictive.deep¶
Requiere
pip install estadistica-ambiental[deep](PyTorch).
deep ¶
Modelos de Deep Learning: LSTM, BiLSTM y GRU para series temporales ambientales.
Requiere: pip install estadistica-ambiental[deep] (torch) Si PyTorch no está disponible, el import falla gracefully con ImportError.
Todas las clases implementan el contrato :class:BaseModel y, además, exponen
los miembros del protocolo :class:ModelSpec (warm_starts, suggest_params,
build_model, search_space) para integrarse en el pipeline de
optimización bayesiana y en :func:estadistica_ambiental.evaluation.backtesting.walk_forward.
BiLSTMModel ¶
GRUModel ¶
LSTMModel ¶
LSTMModel(lookback: int = 24, hidden_size: int = 64, n_layers: int = 2, dropout: float = 0.1, epochs: int = 50, lr: float = 0.001)
Bases: BaseModel
LSTM para pronóstico ambiental univariado con ventana deslizante.
Implementa :class:BaseModel (fit/predict/is_fitted) y el
protocolo :class:ModelSpec (warm_starts/suggest_params/
build_model/search_space) para uso directo con
:func:walk_forward y el optimizador bayesiano.
Requiere: pip install torch (o el extra [deep]).
predictive.bayesian¶
Requiere
pip install estadistica-ambiental[bayes](PyMC + ArviZ). Ver ADR-016.
bayesian ¶
Modelos bayesianos para series y panel ambiental con PyMC.
Requiere: pip install estadistica-ambiental[bayes] (pymc + arviz).
Implementaciones:
- :class:
BayesianARIMA: ARIMA(p, d, q) bayesiano con priorsNormal(0, 1)sobre coeficientes AR/MA yHalfNormal(1)sobre la innovación. Pronóstico vía simulación recursiva del posterior (q=0 usa la matriz de lags AR; q>0 simula los errores MA junto con los lags). - :class:
HierarchicalModel: modelo normal jerárquico (partial pooling) sobre un panel[group_col, value_col]con hiperprior global y media por grupo.
Si PyMC no está instalado el módulo se carga igual y la instanciación de las
clases lanza ImportError con instrucciones claras (mismo patrón que
predictive/deep.py). El registro central solo expone estos modelos cuando
PyMC está disponible.
BayesianARIMA ¶
BayesianARIMA(p: int = 1, d: int = 0, q: int = 0, samples: int = 1000, tune: int = 500, chains: int = 2, seed: int = 42, *, order: Optional[Tuple[int, int, int]] = None, draws: Optional[int] = None, random_seed: Optional[int] = None)
Bases: BaseModel
ARIMA(p, d, q) bayesiano con PyMC.
Priors
intercept ~ Normal(0, 1)phi[i] ~ Normal(0, 1)(coeficientes AR)theta[j] ~ Normal(0, 1)(coeficientes MA, solo si q > 0)sigma ~ HalfNormal(1)(innovación)
El modelo se ajusta sobre la serie diferenciada d veces. La verosimilitud
es Normal(mu, sigma) con mu igual a la suma autoregresiva (más MA si
procede) sobre los lags observados.
Parameters¶
p, d, q : int, opcional
Órdenes del proceso ARIMA. Pueden pasarse posicionalmente o vía
order=(p, d, q).
samples : int
Número de draws por cadena (alias: draws).
tune : int
Pasos de tuneo de NUTS por cadena.
chains : int
Número de cadenas MCMC.
seed : int
Semilla aleatoria (alias: random_seed).
fit ¶
Ajusta ARIMA(p, d, q) bayesiano a la serie y.
X se acepta por compatibilidad con la interfaz :class:BaseModel
pero se ignora en esta versión. Aplica diferenciación d antes de
ajustar y guarda los anclajes necesarios para invertirla en
:meth:predict.
plot_trace ¶
Wrapper sobre arviz.plot_trace del posterior ajustado.
posterior_predictive_interval ¶
Intervalo HDI del posterior predictivo (mean, lower, upper).
predict ¶
predict(horizon: int, X_future: Optional[DataFrame] = None, n_samples: Optional[int] = None, return_samples: bool = False) -> Union[pd.Series, np.ndarray]
Pronóstico posterior predictivo a horizon pasos.
Por defecto devuelve una :class:pandas.Series con la media del
posterior predictivo (indexada por fechas futuras si la serie original
era datetime).
Si return_samples=True o si se pasa n_samples explícito,
devuelve un np.ndarray de forma (n_samples, horizon) con las
trayectorias muestreadas (compatible con la API histórica).
Si n_samples (o el default interno de 500 cuando no se pasa)
supera los draws del posterior (chains * draws), las trayectorias
se completan por bootstrap con reemplazo de ese posterior: la forma
pedida siempre se respeta, pero la incertidumbre de parámetros sigue
acotada por el posterior real -- solo se agregan nuevas realizaciones
de la innovación. Con n_samples muy grande, el costo crece
linealmente (el simulador es un loop en Python puro).
predict_interval ¶
Intervalo de credibilidad por horizonte (mean, lower, upper).
HierarchicalModel ¶
HierarchicalModel(group_col: str = 'estacion', samples: int = 1000, tune: int = 500, chains: int = 2, seed: int = 42, *, draws: Optional[int] = None, random_seed: Optional[int] = None)
Bases: BaseModel
Modelo normal jerárquico con partial pooling por grupo.
Estructura del modelo::
mu_global ~ Normal(0, 10)
sigma_global ~ HalfNormal(5)
mu_group[i] ~ Normal(mu_global, sigma_global)
sigma ~ HalfNormal(5)
y[i] ~ Normal(mu_group[group[i]], sigma)
Acepta entrada en formato largo (DataFrame con columnas
[group_col, value_col]) o, retro-compatiblemente, una serie y y un
array de grupos vía groups= o X['estacion'].
fit ¶
fit(y: Union[Series, DataFrame], X: Optional[DataFrame] = None, groups: Optional[Sequence] = None, value_col: Optional[str] = None, samples: Optional[int] = None) -> 'HierarchicalModel'
Ajusta el modelo jerárquico.
Dos formas de uso:
- Formato largo:
fit(df, value_col="y")condfque tiene la columnaself.group_coly la columnavalue_col. - Compatibilidad:
fit(y_series, groups=array)ofit(y_series, X=df_con_columna_estacion).
group_estimates ¶
Tabla por grupo con media posterior y HDI 95% de mu_group[i].
plot_forest ¶
Wrapper sobre arviz.plot_forest para los efectos por grupo.
predict ¶
Trayectorias por grupo: array (n_samples, horizon, n_groups).
El modelo no es temporal: cada paso muestrea independientemente del
posterior conjunto sobre (mu_group, sigma).
Si n_samples (500 por defecto) supera los draws del posterior
(chains * draws), se completa por bootstrap con reemplazo -- la
forma pedida siempre se respeta, pero la incertidumbre de parámetros
sigue acotada por el posterior real.
predictive.prophet_model¶
Requiere
pip install estadistica-ambiental[prophet].
prophet_model ¶
Modelo Prophet (Meta) con interfaz BaseModel.
ProphetModel ¶
predictive.residual_ar¶
residual_ar ¶
Calibrador AR(1) horario doble-escala sobre residuos de modelos ML.
Implementa el patrón validado en el proyecto CAR (calidad del aire, Cundinamarca): añade autocorrelación realista a pronósticos deterministas (RF/XGB) ajustando 24 modelos AR(1) (uno por hora del día) con varianza de innovación estacional (σ por mes). Genera trayectorias Monte Carlo para construir bandas P10/P50/P90, y expone una suite de tests formales (T1-T4 + KS + Ljung-Box + Jarque-Bera) que devuelven PASS/FAIL.
Adaptado de boa-sarima-forecaster / proyecto CAR
(06_Pronostico_2026/08_escalar_ar1_todas_estaciones.py) por Dan Méndez —
2026-05-07. Ver Plan/Plan.md §13 / M-02 y
Plan/Feedback/repo_estadistica_ambiental_feedback.md §3.1.B.
CalibrationReport
dataclass
¶
HourlyAR1Calibrator ¶
HourlyAR1Calibrator(n_trajectories: int = DEFAULT_TRAJECTORIES, alpha: float = DEFAULT_ALPHA, random_state: Optional[int] = None)
AR(1) horario doble-escala sobre residuos: 24 phi por hora, σ por mes.
Ajusta una familia de 24 modelos AR(1) (uno por hora del día) sobre los
residuos r(t) = y(t) - base_ML(t) y modela la varianza de innovación
σ²(mes) para captar la estacionalidad mensual andina (clima bimodal).
Modelo::
e_AR(t) = phi_h(t) · e_AR(t-1) + ε(t), ε ~ N(0, σ_mes(t))
Use :meth:fit para calibrar phi_h y σ_mes desde una serie de residuos
indexada por hora, :meth:simulate para generar K trayectorias Monte
Carlo, y :meth:validate para correr la suite de 7 tests formales.
fit ¶
fit(residuals: Series | ndarray, datetime_index: Optional[DatetimeIndex] = None) -> 'HourlyAR1Calibrator'
Ajusta 24 phi (uno por hora) y 12 σ (uno por mes) desde residuos.
percentiles ¶
percentiles(trajectories: ndarray, levels: Tuple[float, float, float] = (10.0, 50.0, 90.0)) -> Dict[str, np.ndarray]
Devuelve percentiles P10/P50/P90 (o niveles dados) por paso.
simulate ¶
simulate(horizon: int, n_trajectories: Optional[int] = None, start_datetime: Optional[Timestamp] = None, e0: float = 0.0, random_state: Optional[int] = None) -> np.ndarray
Genera K trayectorias Monte Carlo de longitud horizon.
validate ¶
validate(residuals: Optional[Series | ndarray] = None, datetime_index: Optional[DatetimeIndex] = None, alpha: Optional[float] = None) -> Dict[str, TestResult]
Ejecuta T1-T4 + KS + Ljung-Box + Jarque-Bera sobre las innovaciones.
TestResult
dataclass
¶
predictive.spatial_models¶
spatial_models ¶
Modelos espaciales: Kriging y Gaussian Process con interfaz BaseModel.
KrigingInterpolator ¶
KrigingInterpolator(variogram_model: str = 'spherical', lat_col: str = 'lat', lon_col: str = 'lon', value_col: str = 'valor')
Wrapper de pykrige.OrdinaryKriging para uso en pipelines del repo.
No hereda BaseModel porque opera en espacio 2D, no en tiempo. Interfaz: fit(points_df) → predict(grid_lat, grid_lon).
SpatioTemporalKriging ¶
Kriging espacio-temporal simplificado: ajusta un Kriging por período.
Para cada timestamp, interpola espacialmente las estaciones disponibles. Útil para mapas de PM2.5 o temperatura por fecha.
predictive.registry¶
registry ¶
Evaluación¶
evaluation.metrics¶
metrics ¶
Métricas de evaluación para modelos ambientales. Adaptado de boa-sarima-forecaster/metrics.py por Dan Méndez — 2026-04-22
Extiende las métricas financieras originales con NSE y KGE (hidrología) y desactiva RMSLE para variables que pueden ser negativas (ADR-003).
compare_models ¶
Tabla comparativa de modelos. results = {model_name: metrics_dict}.
evaluate ¶
evaluate(y_true: ndarray, y_pred: ndarray, domain: str = 'general', y_train: Optional[ndarray] = None, ica_breakpoints: Optional[dict] = None, pollutant: str = 'pm25') -> dict
Calcula todas las métricas relevantes según el dominio.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
domain
|
str
|
'general' | 'hydrology' | 'air_quality' |
'general'
|
y_train
|
Optional[ndarray]
|
serie de entrenamiento para MASE (opcional). |
None
|
ica_breakpoints
|
Optional[dict]
|
puntos de corte ICA custom para hit_rate_ica.
Si se provee, tiene precedencia sobre |
None
|
pollutant
|
str
|
contaminante para seleccionar breakpoints ICA correctos ('pm25', 'pm10', 'o3', 'no2', 'so2', 'co'). Solo aplica con domain='air_quality' y sin ica_breakpoints explícito. |
'pm25'
|
hit_rate_ica ¶
hit_rate_ica(y_true: ndarray, y_pred: ndarray, breakpoints: Optional[dict] = None, pollutant: str = 'pm25') -> float
Porcentaje de predicciones en la misma categoría ICA que el valor real.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
ndarray
|
valores reales de concentración (µg/m³, o mg/m³ para CO). |
required |
y_pred
|
ndarray
|
valores predichos de concentración. |
required |
breakpoints
|
Optional[dict]
|
dict con {categoria: (min_excl, max_incl)} personalizado.
Si se provee, tiene precedencia sobre |
None
|
pollutant
|
str
|
contaminante para seleccionar breakpoints de Res. 2254/2017. Opciones: 'pm25', 'pm10', 'o3', 'no2', 'so2', 'co'. Default: 'pm25'. |
'pm25'
|
Returns:
| Type | Description |
|---|---|
float
|
float entre 0.0 y 100.0 (porcentaje de coincidencias de categoría). |
kge ¶
Kling-Gupta Efficiency. Rango (-∞, 1]; 1=perfecto.
mase ¶
Mean Absolute Scaled Error. Requiere serie de entrenamiento o usa naive.
nrmse ¶
RMSE normalizado por desviación estándar. Estable con ceros y negativos.
NRMSE = RMSE / std(y_true). Rango (0, inf), escala-invariante. NRMSE < 1.0 indica mejor desempeño que el modelo de la media. Reemplaza sMAPE cuando la serie contiene valores cercanos a cero. Retorna nan si y_true tiene varianza cero (sensor saturado, fold degenerado).
nse ¶
Nash-Sutcliffe Efficiency. Rango (-∞, 1]; 1=perfecto, <0=peor que media.
pbias ¶
Percent Bias (%). Positivo = sobreestimación.
evaluation.backtesting¶
backtesting ¶
Backtesting walk-forward para modelos predictivos ambientales.
compare_backtests ¶
Tabla comparativa de modelos backtested.
results = {model_name: walk_forward_result_dict}
walk_forward ¶
walk_forward(model: BaseModel, y: Series, horizon: int = 1, n_splits: int = 5, min_train_size: Optional[int] = None, X: Optional[DataFrame] = None, domain: str = 'general', strategy: str = 'expanding', pollutant: str = 'pm25', gap: int = 0) -> Dict
Walk-forward backtesting con ventana expansiva o deslizante.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
BaseModel
|
Instancia de BaseModel (se re-entrena en cada fold). |
required |
y
|
Series
|
Serie temporal objetivo. |
required |
horizon
|
int
|
Pasos a predecir en cada fold. |
1
|
n_splits
|
int
|
Número de folds. |
5
|
min_train_size
|
Optional[int]
|
Tamaño mínimo del conjunto de entrenamiento. |
None
|
X
|
Optional[DataFrame]
|
Exógenas (si el modelo las soporta). |
None
|
domain
|
str
|
'general' | 'hydrology' | 'air_quality' para métricas. |
'general'
|
strategy
|
str
|
'expanding' (crece) | 'sliding' (tamaño fijo). |
'expanding'
|
pollutant
|
str
|
Contaminante para breakpoints ICA ('pm25', 'pm10', 'o3', 'no2', 'so2', 'co'). Solo aplica con domain='air_quality'. |
'pm25'
|
gap
|
int
|
Observaciones de purga entre fin de train y comienzo de test. Evita leakage por autocorrelación alta (PM2.5 horario, caudal diario). Default 0 (sin purga) para compatibilidad retroactiva. |
0
|
Returns:
| Type | Description |
|---|---|
Dict
|
Dict con 'metrics' (promedio), 'folds' (lista por fold) y 'predictions'. |
evaluation.anomaly¶
anomaly ¶
Detección de anomalías en predicciones de modelos. Adaptado de tesis-renare-v4/residual_analysis.py por Dan Méndez — 2026-04-22
El error relativo |real - pred| / (|real| + 1) es estable con valores cercanos a cero y negativos, lo que lo hace adecuado para variables ambientales de escala variable (emisiones, caudal, concentraciones).
anomaly_summary ¶
Resumen estadístico del DataFrame producido por detect_anomalies().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
anomaly_df
|
DataFrame
|
salida de detect_anomalies(). |
required |
threshold
|
float
|
mismo valor usado en detect_anomalies(); se usa solo como fallback si anomaly_df.attrs no tiene 'umbral' guardado. |
2.0
|
Returns:
| Type | Description |
|---|---|
dict
|
dict con: - n_total: número total de registros evaluados - n_anomalies: cantidad de anomalías detectadas - pct_anomalies: porcentaje de anomalías sobre el total - mean_error_rel: error relativo medio (toda la serie) - std_error_rel: desviación estándar del error relativo (ddof=0) - threshold_value: umbral exacto aplicado en detect_anomalies - max_error_rel: error relativo máximo observado |
detect_anomalies ¶
detect_anomalies(y_true: Union[ndarray, Series], y_pred: Union[ndarray, Series], threshold: float = 2.0, relative: bool = True, index: Optional[Index] = None) -> pd.DataFrame
Detecta registros donde el error del modelo supera threshold desviaciones estándar.
Lógica
- Si relative=True: error_rel = |real - pred| / (|real| + 1)
- Si relative=False: error_rel = |real - pred| (error absoluto)
- Anomalía: error_rel > mean(error_rel) + threshold * std(error_rel)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
Union[ndarray, Series]
|
valores reales observados. |
required |
y_pred
|
Union[ndarray, Series]
|
valores predichos por el modelo. |
required |
threshold
|
float
|
número de desviaciones estándar sobre la media para declarar anomalía. |
2.0
|
relative
|
bool
|
si True usa error relativo (recomendado para series con ceros). |
True
|
index
|
Optional[Index]
|
índice opcional (ej. fechas) para el DataFrame resultante. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame con columnas: - y_true: valor real - y_pred: valor predicho - error: residual (y_true - y_pred) - error_rel: error relativo o absoluto según parámetro relative - is_anomaly: booleano — True si supera el umbral |
DataFrame
|
Ordenado por error_rel descendente. |
evaluation.comparison¶
comparison ¶
Comparación multi-criterio y selección del mejor modelo predictivo.
rank_models ¶
rank_models(results: Dict[str, Dict], domain: str = 'general', weights: Optional[Dict[str, float]] = None) -> pd.DataFrame
Ranking multi-criterio de modelos backtestados.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
results
|
Dict[str, Dict]
|
{model_name: walk_forward_result} — salida de walk_forward(). |
required |
domain
|
str
|
'general' | 'hydrology' | 'air_quality'. |
'general'
|
weights
|
Optional[Dict[str, float]]
|
Pesos custom {metric: weight}. Sobreescribe defaults. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame ordenado por score compuesto (menor es mejor). |
select_best ¶
Devuelve el nombre del mejor modelo según ranking compuesto.
Features¶
features.climate¶
climate ¶
Covariables de cambio climático: índices ENSO, ONI, escenarios.
Estas covariables se usan en modelos predictivos de oferta hídrica, páramos, humedales y gestión de riesgo cuando hay influencia climática.
enso_dummy ¶
Une el índice ONI al DataFrame principal y agrega dummies de fase.
enso_lagged ¶
enso_lagged(df: DataFrame, oni_df: DataFrame, date_col: str, linea_tematica: Optional[str] = None, lag_meses: Optional[int] = None) -> pd.DataFrame
Une el índice ONI con el lag específico por línea temática colombiana.
El lag captura el retraso entre la señal ENSO y su respuesta en la variable ambiental local (e.g. caudal, PM2.5, nivel de humedal).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
DataFrame con datos ambientales. |
required |
oni_df
|
DataFrame
|
DataFrame devuelto por load_oni(). |
required |
date_col
|
str
|
Columna de fechas en df. |
required |
linea_tematica
|
Optional[str]
|
Nombre de la línea ('oferta_hidrica', 'calidad_aire', etc.). Determina el lag automáticamente desde config.ENSO_LAG_MESES. |
None
|
lag_meses
|
Optional[int]
|
Override manual del lag. Tiene precedencia sobre linea_tematica. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
df con columnas oni_lag{n}, fase_lag{n}, intensidad_lag{n}, dummies. |
load_oni ¶
Carga el Índice Oceánico Niño (ONI) de NOAA o desde archivo local.
El ONI es el índice estándar para clasificar El Niño/La Niña, con impacto directo en precipitación y temperatura en Colombia.
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame con columnas: fecha, oni, fase, intensidad. |
features.lags¶
lags ¶
Feature engineering: lags, rolling stats y diferencias para series ambientales.
add_diff_features ¶
Agrega diferencias de orden N (útil para eliminar tendencia).
add_lags ¶
Agrega columnas lag_N para la variable objetivo.
add_rolling_features ¶
add_rolling_features(df: DataFrame, col: str, windows: List[int], stats: List[str] = ('mean', 'std', 'min', 'max'), drop_na: bool = False) -> pd.DataFrame
Agrega estadísticas rodantes para capturar tendencia local.
features.calendar¶
calendar ¶
Features de calendario para series ambientales colombianas.
add_calendar_features ¶
add_calendar_features(df: DataFrame, date_col: str, features: tuple = ('hour', 'dayofweek', 'month', 'quarter', 'dayofyear'), cyclical: bool = True) -> pd.DataFrame
Agrega variables de calendario como features numéricas.
Con cyclical=True codifica como seno/coseno para preservar la estructura cíclica (e.g. hora 23 ≈ hora 0).
features.exogenous¶
exogenous ¶
Preparación de variables exógenas para modelos SARIMAX y ML.
align_exogenous ¶
align_exogenous(df_target: DataFrame, df_exog: DataFrame, date_col_target: str, date_col_exog: str, exog_cols: Optional[List[str]] = None, freq: str = 'D', fill_method: str = 'linear') -> pd.DataFrame
Alinea un DataFrame de exógenas con la serie objetivo por fecha.
Remuestrea las exógenas a la frecuencia de la serie objetivo, rellena faltantes y hace merge. Útil para combinar datos de calidad del aire con meteorología de diferente resolución temporal.
create_exog_matrix ¶
create_exog_matrix(df: DataFrame, cols: List[str], date_col: str, train_end_idx: int) -> Dict[str, pd.DataFrame]
Divide las exógenas en train y future para SARIMAX.
meteorological_features ¶
meteorological_features(df: DataFrame, temp_col: Optional[str] = None, wind_col: Optional[str] = None, humidity_col: Optional[str] = None, rain_col: Optional[str] = None) -> pd.DataFrame
Genera features derivados de variables meteorológicas.
- Índice de confort térmico (temperatura × humedad)
- Indicador de lluvia binario
- Velocidad de viento al cuadrado (proxy de dispersión)
Optimización¶
optimization.bayes_opt¶
bayes_opt ¶
Motor de optimización bayesiana con Optuna TPE. Adaptado de boa-sarima-forecaster/optimizer.py por Dan Méndez — 2026-04-22
Generalizado: soporta cualquier función objetivo y espacio de búsqueda, no solo SARIMA. Usado por predictive/classical.py y demás modelos.
Mejoras incorporadas (v2):
- optimize_model: acepta cualquier objeto que satisfaga el protocolo
ModelSpec (warm_starts, suggest_params, build_model).
- Warm-start: encola configuraciones conocidas antes de la búsqueda TPE.
- Graceful fallback: si Optuna falla N veces seguidas usa warm_start[0].
- MedianPruner: descarta trials malos temprano para ahorrar tiempo.
- Devuelve OptimizationResult tipado en lugar del Study crudo.
best_params ¶
Devuelve los mejores hiperparámetros del estudio.
optimization_history ¶
Historial de trials como DataFrame (requiere optuna visualización).
optimize ¶
optimize(objective: Callable[[Trial], float], n_trials: int = 50, timeout: Optional[int] = None, direction: str = 'minimize', study_name: Optional[str] = None, storage: Optional[str] = None, show_progress: bool = False, warm_starts: Optional[List[Dict[str, Any]]] = None) -> optuna.Study
Ejecuta optimización bayesiana TPE sobre la función objetivo.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
objective
|
Callable[[Trial], float]
|
Función que recibe un Trial de Optuna y devuelve el valor a minimizar (o maximizar si direction='maximize'). |
required |
n_trials
|
int
|
Número de evaluaciones. |
50
|
timeout
|
Optional[int]
|
Tiempo límite en segundos (None = sin límite). |
None
|
direction
|
str
|
'minimize' | 'maximize'. |
'minimize'
|
study_name
|
Optional[str]
|
Nombre del estudio (opcional). |
None
|
storage
|
Optional[str]
|
URL de base de datos Optuna para persistencia (opcional). |
None
|
show_progress
|
bool
|
Mostrar barra de progreso en consola. |
False
|
warm_starts
|
Optional[List[Dict[str, Any]]]
|
Lista de dicts de hiperparámetros que se encolan como trials iniciales antes de la exploración aleatoria. Si se provee, Optuna parte de configuraciones conocidas en lugar de explorar ciegamente. |
None
|
Returns:
| Type | Description |
|---|---|
Study
|
optuna.Study con el historial completo de la búsqueda. |
optimize_model ¶
optimize_model(model_spec: Any, objective: Callable[[Trial], float], n_trials: int = 50, timeout: Optional[int] = None, direction: str = 'minimize', study_name: Optional[str] = None, storage: Optional[str] = None, show_progress: bool = False, max_fallos: int = _MAX_FALLOS_CONSECUTIVOS) -> 'OptimizationResult'
Optimiza los hiperparámetros de un modelo que sigue el protocolo ModelSpec.
Esta función extiende :func:optimize con soporte explícito para el
protocolo ModelSpec:
- Si
model_spectienewarm_starts, los inyecta como trials iniciales antes de la exploración aleatoria de Optuna. - Si Optuna acumula
max_fallosexcepciones consecutivas (o falla completamente), activa el fallback usandowarm_starts[0]como parámetros por defecto en lugar de propagar la excepción. - Construye el modelo final con
model_spec.build_model(best_params)si el método está disponible.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_spec
|
Any
|
Objeto que implementa el protocolo |
required |
objective
|
Callable[[Trial], float]
|
Función |
required |
n_trials
|
int
|
Número total de evaluaciones de Optuna. |
50
|
timeout
|
Optional[int]
|
Tiempo límite en segundos (None = sin límite). |
None
|
direction
|
str
|
'minimize' | 'maximize'. |
'minimize'
|
study_name
|
Optional[str]
|
Nombre del estudio Optuna (opcional). |
None
|
storage
|
Optional[str]
|
URL de base de datos Optuna para persistencia (opcional). |
None
|
show_progress
|
bool
|
Mostrar barra de progreso en consola. |
False
|
max_fallos
|
int
|
Fallos consecutivos tolerados antes de activar fallback. |
_MAX_FALLOS_CONSECUTIVOS
|
Returns:
| Type | Description |
|---|---|
'OptimizationResult'
|
class: |
'OptimizationResult'
|
con |
'OptimizationResult'
|
|
optimize_sarima ¶
optimize_sarima(series: 'pd.Series', n_trials: int = 50, max_p: int = 5, max_q: int = 5, seasonal_period: int = 12, n_splits: int = 3, horizon: int = 1, gap: int = 0, timeout: Optional[int] = None) -> 'OptimizationResult'
Wrapper convenience para optimizar hiperparámetros SARIMA con Optuna.
Uso::
from estadistica_ambiental.optimization.bayes_opt import optimize_sarima
result = optimize_sarima(serie_caudal, n_trials=50)
mejor_modelo = result.model # SARIMAModel listo para fit()
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
series
|
'pd.Series'
|
Serie temporal objetivo (pd.Series con DatetimeIndex). |
required |
n_trials
|
int
|
Evaluaciones de Optuna. |
50
|
max_p
|
int
|
Máximo orden AR (p). |
5
|
max_q
|
int
|
Máximo orden MA (q). |
5
|
seasonal_period
|
int
|
Período estacional S (default 12 para datos mensuales). |
12
|
n_splits
|
int
|
Folds del walk-forward dentro del objetivo. |
3
|
horizon
|
int
|
Horizonte de pronóstico en el objetivo. |
1
|
gap
|
int
|
Purga entre train y test (ver walk_forward). |
0
|
timeout
|
Optional[int]
|
Tiempo límite en segundos. |
None
|
Returns:
| Type | Description |
|---|---|
'OptimizationResult'
|
OptimizationResult con best_params, best_score y model construido. |
sarima_search_space ¶
sarima_search_space(trial: Trial, max_p: int = 5, max_d: int = 2, max_q: int = 5, max_P: int = 2, max_D: int = 1, max_Q: int = 2, seasonal_period: int = 12) -> Dict[str, int]
Espacio de búsqueda estándar para SARIMA (p,d,q)(P,D,Q,s).
xgboost_search_space ¶
Espacio de búsqueda estándar para XGBoost.
Análisis espacial¶
Requiere
pip install estadistica-ambiental[spatial](geopandas + rasterio + pysal + esda + folium). Ver ADR-013 endecisiones.md.
spatial.io¶
io ¶
I/O espacial: lectura de SHP, GeoPackage, GeoJSON, NetCDF y raster.
Complementa io/loaders.py para formatos con componente geométrico.
list_gpkg_layers ¶
Lista las capas disponibles en un GeoPackage.
load_netcdf_spatial ¶
load_netcdf_spatial(path: Union[str, Path], variable: Optional[str] = None, time_slice: Optional[slice] = None) -> 'xarray.Dataset'
Carga un NetCDF como xarray Dataset (datos espacio-temporales).
Útil para datos Copernicus, IDEAM o modelos climáticos. Requiere: xarray + netcdf4.
load_raster ¶
Carga un raster GeoTIFF/NetCDF y devuelve datos + metadatos.
Returns dict con: data (np.ndarray), transform, crs, shape, nodata. Requiere: rasterio.
load_vector ¶
load_vector(path: Union[str, Path], layer: Optional[str] = None, to_epsg: Optional[int] = None) -> 'geopandas.GeoDataFrame'
Carga un archivo vectorial (SHP, GeoPackage, GeoJSON) a GeoDataFrame.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Union[str, Path]
|
Ruta al archivo. |
required |
layer
|
Optional[str]
|
Capa específica (para GeoPackage con múltiples capas). |
None
|
to_epsg
|
Optional[int]
|
Reprojecta al EPSG indicado tras la carga. |
None
|
vector_to_parquet ¶
Guarda un GeoDataFrame como GeoParquet (formato eficiente para SIG).
spatial.projections¶
projections ¶
Manejo de proyecciones geográficas para datos ambientales colombianos.
Sistemas de referencia más usados en Colombia
MAGNA-SIRGAS geográfico EPSG:4686 MAGNA-SIRGAS / CTM12 EPSG:9377 (proyección oficial desde 2020) WGS84 EPSG:4326 (GPS, OpenStreetMap) Web Mercator EPSG:3857 (visualización web)
bounding_box_colombia ¶
Bounding box de Colombia en WGS84 (lon_min, lat_min, lon_max, lat_max).
clip_to_colombia ¶
Recorta un GeoDataFrame al territorio colombiano.
points_to_geodataframe ¶
points_to_geodataframe(df: DataFrame, lat_col: str = 'lat', lon_col: str = 'lon', epsg: int = EPSG_WGS84)
Convierte un DataFrame con lat/lon a GeoDataFrame de puntos.
reproject ¶
Reprojecta un GeoDataFrame entre sistemas de referencia.
spatial.analysis¶
analysis ¶
Análisis espacial: traslapes poligonales y estadísticas zonales.
Operaciones fundamentales para análisis de iniciativas GEI, áreas protegidas y agregación de variables ambientales por unidades político-administrativas.
intersection_area ¶
intersection_area(gdf1: 'geopandas.GeoDataFrame', gdf2: 'geopandas.GeoDataFrame', id_col1: str, id_col2: str) -> 'geopandas.GeoDataFrame'
Calcula áreas de traslape entre dos capas poligonales.
Reprojecta a CTM12 (EPSG:9377) para precisión métrica en Colombia. Usa overlay vectorizado de geopandas (no bucle anidado).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
gdf1
|
'geopandas.GeoDataFrame'
|
Primera capa poligonal (ej: iniciativas REDD+). |
required |
gdf2
|
'geopandas.GeoDataFrame'
|
Segunda capa poligonal (ej: áreas protegidas, páramos). |
required |
id_col1
|
str
|
Columna identificadora única en gdf1. |
required |
id_col2
|
str
|
Columna identificadora única en gdf2. |
required |
Returns:
| Type | Description |
|---|---|
'geopandas.GeoDataFrame'
|
GeoDataFrame con columnas: id_col1, id_col2, intersection_area_m2, |
'geopandas.GeoDataFrame'
|
pct_of_ |
zonal_statistics ¶
zonal_statistics(raster_path: Union[str], zones_gdf: 'geopandas.GeoDataFrame', zone_id_col: str, stats: List[str] = None) -> 'geopandas.GeoDataFrame'
Agrega valores de raster por zonas poligonales (municipios, departamentos).
Equivalente a QGIS "Zonal Statistics" o ArcGIS "Zonal Statistics as Table". Caso de uso típico: emisiones GEI o deforestación por municipio/departamento.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
raster_path
|
Union[str]
|
Ruta a GeoTIFF (deforestación, emisiones, NDVI, etc.) |
required |
zones_gdf
|
'geopandas.GeoDataFrame'
|
GeoDataFrame con polígonos de zonas. |
required |
zone_id_col
|
str
|
Columna de identificación única (ej: 'CODIGO_DANE'). |
required |
stats
|
List[str]
|
Estadísticas a calcular. Default: ['mean', 'sum', 'std', 'min', 'max']. Opciones adicionales: 'count', 'median'. |
None
|
Returns:
| Type | Description |
|---|---|
'geopandas.GeoDataFrame'
|
GeoDataFrame original con columnas adicionales para cada estadística. |
spatial.autocorrelation¶
autocorrelation ¶
Autocorrelación espacial: I de Moran, C de Geary.
Previo a modelos espaciales para verificar que existe dependencia espacial.
geary_c ¶
Índice C de Geary para autocorrelación espacial.
Complementa a I de Moran: más sensible a disimilitud local. C ≈ 1 → aleatoriedad; C < 1 → clustering; C > 1 → dispersión.
Requiere: pip install pysal esda libpysal (incluido en [spatial]).
getis_ord_g ¶
G* de Getis-Ord local — detección de hotspots y coldspots.
Identifica clusters de valores altos (hotspots) y bajos (coldspots) estadísticamente significativos. Útil para deforestación, contaminación.
Agrega columnas 'g_z' (z-score) y 'hotspot' ('hot'/'cold'/'ns') al GeoDataFrame. Requiere: esda, libpysal (incluido en [spatial]).
local_morans_i ¶
LISA — Moran local para identificar clusters y outliers espaciales.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
weight_type
|
str
|
'queen', 'rook' o 'kN' (ej. 'k5') — ver _build_weights(). |
'queen'
|
Requiere: pip install pysal esda libpysal (incluido en [spatial]). Agrega columnas 'lisa_q' (cuadrante) y 'lisa_p' al GeoDataFrame.
morans_i ¶
Índice de Moran global para autocorrelación espacial.
Requiere: pip install pysal esda libpysal (incluido en [spatial]).
H0: distribución espacialmente aleatoria. I > 0 → clustering; I < 0 → dispersión.
spatial.interpolation¶
interpolation ¶
Interpolación espacial: IDW y Kriging (ordinario, universal).
Usado para mapear contaminantes o variables hídricas entre estaciones dispersas.
idw ¶
idw(points: DataFrame, lat_col: str, lon_col: str, value_col: str, grid_lat: ndarray, grid_lon: ndarray, power: float = 2.0) -> np.ndarray
Interpolación por Distancia Inversa Ponderada (IDW).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
DataFrame
|
DataFrame con estaciones de observación. |
required |
lat_col
|
str
|
Nombre de la columna de latitud en |
required |
lon_col
|
str
|
Nombre de la columna de longitud en |
required |
value_col
|
str
|
Nombre de la columna con el valor a interpolar. |
required |
grid_lat
|
ndarray
|
Grid 2D de latitudes objetivo (meshgrid). |
required |
grid_lon
|
ndarray
|
Grid 2D de longitudes objetivo (meshgrid). |
required |
power
|
float
|
Exponente del IDW (2 = estándar). |
2.0
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Array 2D con valores interpolados en la grilla. |
ordinary_kriging ¶
ordinary_kriging(points: DataFrame, lat_col: str, lon_col: str, value_col: str, grid_lat: ndarray, grid_lon: ndarray, variogram_model: str = 'spherical') -> Tuple[np.ndarray, np.ndarray]
Kriging ordinario vía pykrige.
Requiere: pip install pykrige (incluido en [spatial]).
Returns:
| Type | Description |
|---|---|
Tuple[ndarray, ndarray]
|
(z_interpolated, z_variance) — ambos arrays 2D. |
universal_kriging ¶
universal_kriging(points: DataFrame, lat_col: str, lon_col: str, value_col: str, grid_lat: ndarray, grid_lon: ndarray, variogram_model: str = 'linear', drift_order: int = 1) -> Tuple[np.ndarray, np.ndarray]
Kriging universal con tendencia espacial (drift polinomial).
Extiende el Kriging ordinario modelando un drift determinístico. Ideal para variables con gradiente espacial claro: temperatura, elevación, presión antrópica sobre ecosistemas.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
drift_order
|
int
|
1=lineal (default), 2=cuadrático. |
1
|
variogram_model
|
str
|
'linear', 'spherical', 'exponential', 'gaussian'. |
'linear'
|
Returns:
| Type | Description |
|---|---|
Tuple[ndarray, ndarray]
|
(z_interpolated, z_variance) — ambos arrays 2D. |
spatial.viz¶
viz ¶
Visualización espacial: mapas de estaciones, interpolación y coropletas.
choropleth_map ¶
choropleth_map(gdf, value_col: str, title: str = 'Mapa', cmap: str = 'YlOrRd', zoom: int = 6) -> 'folium.Map'
Mapa coroplético de un GeoDataFrame con folium + branca.
Requiere: pip install folium branca.
map_stations ¶
map_stations(df: DataFrame, lat_col: str = 'lat', lon_col: str = 'lon', label_col: Optional[str] = None, value_col: Optional[str] = None, title: str = 'Estaciones de monitoreo', zoom: int = 6) -> 'folium.Map'
Mapa interactivo de estaciones con folium.
Requiere: pip install folium (incluido en [spatial]).
plot_kriging_map ¶
plot_kriging_map(grid_lat: ndarray, grid_lon: ndarray, z_values: ndarray, points_df: Optional[DataFrame] = None, lat_col: str = 'lat', lon_col: str = 'lon', title: str = 'Kriging', figsize: tuple = (8, 7)) -> 'plt.Figure'
Mapa estático (matplotlib) del resultado del Kriging.
Reporting¶
reporting.compliance_report¶
compliance_report ¶
Reporte HTML de cumplimiento normativo ambiental colombiano.
Genera un documento HTML que muestra, por variable, el porcentaje de excedencias respecto a las normas colombianas relevantes (Res. 2254/2017, Res. 2115/2007, Res. 631/2015, IUA, ICA, etc.).
Uso típico
from estadistica_ambiental.reporting.compliance_report import compliance_report
compliance_report( df, variables=["pm25", "od", "dbo5"], date_col="fecha", linea_tematica="calidad_aire", output="data/output/reports/cumplimiento_aire.html", )
compliance_report ¶
compliance_report(df: DataFrame, variables: List[str], date_col: str = 'fecha', linea_tematica: Optional[str] = None, estacion_col: Optional[str] = None, output: str = 'data/output/reports/compliance_report.html', title: Optional[str] = None, custom_thresholds: Optional[Dict[str, float]] = None) -> Path
Genera reporte HTML de cumplimiento normativo ambiental colombiano.
Compara cada variable del DataFrame contra todas las normas colombianas registradas para esa variable y produce un HTML con: - Semáforo de cumplimiento global - Tabla de excedencias por variable y norma - Serie temporal con excedencias resaltadas por variable - Contexto de la línea temática (ficha de dominio)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
DataFrame con series temporales ambientales. |
required |
variables
|
List[str]
|
Lista de columnas a evaluar (ej. ['pm25', 'od', 'dbo5']). |
required |
date_col
|
str
|
Columna de fechas. |
'fecha'
|
linea_tematica
|
Optional[str]
|
Nombre de la línea temática para agregar contexto ('calidad_aire', 'recurso_hidrico', 'oferta_hidrica', etc.). |
None
|
estacion_col
|
Optional[str]
|
Columna de estación para reportar en el encabezado. |
None
|
output
|
str
|
Ruta del HTML de salida. |
'data/output/reports/compliance_report.html'
|
title
|
Optional[str]
|
Título del reporte (default: auto-generado). |
None
|
custom_thresholds
|
Optional[Dict[str, float]]
|
Umbrales adicionales {variable: umbral} no incluidos en las normas estándar. |
None
|
Returns:
| Type | Description |
|---|---|
Path
|
Path al archivo HTML generado. |
reporting.forecast_report¶
forecast_report ¶
Reporte HTML automático de pronósticos con comparación de modelos.
forecast_report ¶
forecast_report(y_true: Series, predictions: Dict[str, ndarray], metrics: Dict[str, dict], output: str = 'reports/forecast_report.html', title: str = 'Reporte de Pronóstico', variable_name: str = 'variable', unit: str = '') -> Path
Genera reporte HTML con series reales vs. pronósticos y tabla de métricas.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
Series
|
Serie real (valores observados en el período de test). |
required |
predictions
|
Dict[str, ndarray]
|
{model_name: array_de_predicciones}. |
required |
metrics
|
Dict[str, dict]
|
{model_name: metrics_dict} — salida de evaluate(). |
required |
output
|
str
|
Ruta del HTML de salida. |
'reports/forecast_report.html'
|
title
|
str
|
Título del reporte. |
'Reporte de Pronóstico'
|
variable_name
|
str
|
Nombre de la variable pronosticada. |
'variable'
|
unit
|
str
|
Unidad de medida (e.g. 'µg/m³'). |
''
|
reporting.stats_report¶
stats_report ¶
Reporte HTML de estadística descriptiva e inferencial.
stats_report ¶
stats_report(df: DataFrame, output: str = 'reports/stats_report.html', title: str = 'Reporte Estadístico', date_col: Optional[str] = None, value_cols: Optional[list] = None) -> Path
Genera reporte HTML con estadística descriptiva + inferencial.
Incluye: resumen univariado, estacionariedad y tendencia por columna numérica.
Configuración¶
config¶
config ¶
Configuración central del proyecto Estadística Ambiental. Adaptado de boa-sarima-forecaster/config.py por Dan Méndez — 2026-04-22