Modeling toolkit — regresión lineal simple para pobreza
Utilidad mínima (pero rigurosa) para ajustes lineales orientados a series de pobreza. Sirve para exploración, sanity checks y como baseline reproducible —no reemplaza los modelos del pipeline principal. El contexto y motivación vienen del análisis con Censo 2010, integración geoespacial y métricas derivadas.
1) Especificación del modelo (baseline)
Tomamos como dependiente una serie mensual/trimestral de pobreza (conteo o tasa). Predictoras: empleo (público/privado/resto), actividad (EMAE, centrada) y asequibilidad (CB/RIPTE, IPC/RIPTE; centradas). Señales esperadas: empleo ↓ pobreza (coeficientes negativos), costo de vida relativo ↑ pobreza (coeficientes positivos), actividad ↑ ↓ pobreza.
\[
\text{pobres} = C - \alpha_1 (\# \text{emp\_pub}) - \alpha_2 (\# \text{emp\_priv}) - \alpha_3 (\# \text{emp\_resto})
+ \beta \, (\text{EMAE} - \overline{\text{EMAE}})
+ \gamma \left(\frac{\text{CB}}{\text{RIPTE}} - \overline{\frac{\text{CB}}{\text{RIPTE}}}\right)
+ \delta \left(\frac{\text{IPC}}{\text{RIPTE}} - \overline{\frac{\text{IPC}}{\text{RIPTE}}}\right)
\]
- Racional económico y consideraciones: interacciones potenciales, efectos rezagados (p. ej. EMAE→pobreza con retraso), y multicolinealidad (EMAE vs empleo); evaluar regularización si hace falta.
2) Contrato mínimo (inputs/outputs)
Entradas
- Series
indice_tiempo
(M o Q) alineadas y sin saltos; columnas:Empleo_Publico
,Empleo_Privado
,Empleo_Resto
EMAE
(o desviación vs. media)CB_RIPTE
,IPC_RIPTE
(o versiones centradas)valor
(pobres: número o tasa)
- Opcional: lags p (
EMAE_lag1
, …), dummies estacionales.
Salida
fitted_valor
,residuo
, métricas (R2
, MAE, RMSE), y coeficientes/intercepto.- Artefactos recomendados:
model_linear.json
(coeficientes, signos, standard errors si SM/OLS)fitted.parquet
(con fitted/residuos)- (opcional)
model.pkl
scikit-learn, con pin de versión.
Garantías
- Alineación temporal exacta; sin NaNs en X tras el preprocesado seleccionado (ver §3).
- Trazabilidad:
source_repo@commit
, ventana temporal y escalas usadas.
3) NaNs: dos rutas operativas (eligir una)
Evitá “parches invisibles”. Documentá la política elegida en el notebook.
Ruta A — dropna
explícito (simple y clara)
- Filtrar filas con NaNs en X e y; ajustar y reportar n efectivo.
- Ventaja: reproducible y transparente; Desventaja: reduce muestra si faltantes son frecuentes.
Snippet (A)
from sklearn.linear_model import LinearRegression
X_cols = ['Empleo_Privado','Empleo_Publico','Empleo_Resto',
'EMAE_Centered','CB_RIPTE_Centered','IPC_RIPTE_Centered']
df_ = dep_var.dropna(subset=X_cols + ['valor']).copy()
X, y = df_[X_cols].values, df_['valor'].values
m = LinearRegression().fit(X, y)
df_['fitted_valor'] = m.predict(X)
Ruta B — masked arrays (conservar estructura)
- Usar masked arrays para ignorar NaNs al ajustar, sin reindexar.
- Ventaja: preserva el
indice_tiempo
original; Desventaja: mayor complejidad.
Snippet (B)
import numpy as np
from numpy import ma
from sklearn.linear_model import LinearRegression
X = np.array([ma.masked_invalid(dep_var[c].values) for c in X_cols]).T
y = ma.masked_invalid(dep_var['valor'].values)
m = LinearRegression().fit(ma.compress_rows(X), ma.compressed(y))
mask_valid = ~dep_var[X_cols].isnull().any(axis=1)
dep_var.loc[mask_valid, 'fitted_valor'] = m.predict(ma.compress_rows(X))
4) Preparación de datos (mínimos)
- Centrado: restar la media a EMAE y a las razones CB/RIPTE, IPC/RIPTE (facilita interpretación de C).
- Escalas: usar unidades consistentes (empleo en miles, pobreza en miles o %).
- Alineación: si mezclás mensual/Q, aplicá tu adaptador temporal (ver toolkit temporal).
- Lags e interacciones (opcional): probar 1–2 rezagos en EMAE/empleo; evaluar interacción
EMAE × empleo
.
5) Ajuste y diagnóstico
Ajuste (sklearn)
from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error
yhat = m.predict(X)
R2 = r2_score(y, yhat); MAE = mean_absolute_error(y, yhat); RMSE = mean_squared_error(y, yhat, squared=False)
Chequeos mínimos
- Signos esperados: α’s (empleo) < 0; γ, δ (CB/RIPTE, IPC/RIPTE) > 0; β (EMAE) < 0.
- Residuos: evaluar patrón temporal (autocorrelación); si fuerte, considerar HAC o diferencias.
- Multicolinealidad: inspeccionar correlaciones/vif; considerar Ridge/Lasso si inestables.
Plot de ajuste (opcional, para inspección rápida)
import matplotlib.pyplot as plt
ax = dep_var.set_index('indice_tiempo')[['valor','fitted_valor']].plot()
ax.set_title('Valor vs Ajuste (lineal)'); ax.grid(True)
6) Export y trazabilidad
fitted.parquet
conindice_tiempo, valor, fitted_valor, residuo
.model_linear.json
: coeficientes, intercepto, métricas, ventana temporal, columnas usadas.model.pkl
(opcional) + pin de scikit-learn.
Mantener compatibilidad con políticas de exportación JSON (encoder de timestamps, escritura atómica). Ver metodos/etl_json_policies.
7) Límites y extensiones
- Este baseline no modela estructura de error ni cambios de régimen; úsalo como “termómetro” y para validar signos/ordenes de magnitud.
- Para producción, migrar a: lags seleccionados por criterio, dummies estacionales, regularización, y validación out-of-sample.
8) Errores comunes
- Ajustar con NaNs “silenciosos” → elegir Ruta A o B y dejar rastro en logs.
- No centrar CB/RIPTE e IPC/RIPTE → intercepto poco interpretable.
- Confluir conteo y tasa de pobreza sin escalar → coeficientes sin sentido.
- Omitir la trazabilidad temporal → difícil comparar runs.
9) Referencias cruzadas
- Temporal toolkit (alineación M↔Q, desestacionalización básica).
- Catálogo (definiciones de métricas) y DBML (claves y granularidades).
- ETL JSON (contratos de exportación y merges jerárquicos).