Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Pronóstico de la velocidad del viento a 24 horas en el Caribe colombiano

Curso: Machine Learning · Profesor: Lihki Rubio Ortega Grupo: Yuryen Rollo, Betzaida Ruiz

En este trabajo nos preguntamos si es posible anticipar, con un día de antelación, la velocidad del viento que medirá una estación meteorológica del Caribe colombiano. Para responderlo usamos las mediciones horarias que el IDEAM publica en el Portal Nacional de Datos Abiertos para 76 estaciones de siete departamentos entre 2020 y 2025. Primero describimos los datos y revisamos su calidad; después analizamos su comportamiento en el tiempo y en el espacio; y por último ajustamos un modelo base, un SVR lineal, que comparamos con referencias simples como repetir el valor de hoy.

Reproducibilidad. El notebook trabaja sobre un panel ya procesado (panel_multivariado.csv), que se obtiene a partir de los 24 CSV originales del IDEAM con los scripts de la carpeta scripts/. Los scripts escriben sus resultados en la carpeta desde la que se ejecutan, y el notebook los lee de la carpeta hermana ../ideam_viento/. Desde la carpeta de este repositorio:

mkdir ../ideam_viento
cd ../ideam_viento
python ../entregable1/scripts/procesar_todo.py "<carpeta con los CSV descargados>"            # limpieza original
python ../entregable1/scripts/procesar_todo.py "<carpeta con los CSV descargados>" --causal   # limpieza causal (sección 3) y sensibilidad de 3.6
python ../entregable1/scripts/verificar_conteo.py "<carpeta con los CSV descargados>"

procesar_todo.py ejecuta procesar_variable.py (limpieza de cada variable) y unir_panel.py (unión con el catálogo de estaciones) y escribe el panel y los reportes de auditoría que usa la sección 1.6. Para leer los datos de otra carpeta basta con definir la variable de entorno DATOS_PANEL antes de abrir el notebook. La tabla de umbrales de la sección 1.6 se genera con python scripts/revisar_umbral.py "<carpeta VELOCIDAD DEL VIENTO>" desde la carpeta del repositorio. Todas las semillas aleatorias están fijadas (42) y las versiones de las librerías están en requirements.txt.


1. Base de datos

1.1 Problema de investigación

Queremos saber si la velocidad del viento de mañana, a una hora determinada, se puede predecir en una estación del Caribe colombiano usando únicamente lo que se ha medido hasta hoy. Es un problema de regresión sobre un panel espacio-temporal: cada observación es una estación en una hora, las estaciones tienen coordenadas y sus mediciones forman series de tiempo, así que el análisis tiene que tener en cuenta tanto la dependencia temporal como la espacial (secciones 2.6 a 2.8).

Conviene precisar qué significa “24 horas”. Cada registro horario t es el promedio de la hora que empieza en t; por ejemplo, el valor de las 10:00 resume lo medido entre las 10:00 y las 10:59. Como ese promedio solo existe cuando la hora termina, el pronóstico se emite en t + 1 h, con la hora t como la última completa. La variable objetivo es VViento(t + 24 h): la velocidad media de la hora que empieza 24 h después de la última hora observada. Visto desde el momento en que se emite el pronóstico, la hora objetivo empieza 23 h después y termina 24 h después; en el resto del documento hablamos de horizonte de 24 h en ese sentido.

Un pronóstico así tiene usos concretos: planear la operación del día siguiente en los parques eólicos de La Guajira, en los puertos de Barranquilla, Cartagena y Santa Marta, y en los aeropuertos de la región.

1.2 Selección del conjunto de datos

Antes de llegar a este conjunto evaluamos otras dos fuentes:

DatasetResultadoDecisión
NASA POWER (reanálisis MERRA-2, diario, 42 puntos de malla)Es un modelo de reanálisis con celdas de ≈ 50 km, no una medición: no responde la pregunta sobre el viento medido en cada sitio. Además, el pronóstico diario resultó casi trivial (persistencia R² = 0.94) y el archivo de 2021 estaba desalineadoDescartado
Mendeley (estaciones in situ, diario)Sus estaciones de Atlántico no aparecen en el catálogo oficial DHIME del IDEAM: no es verificableDescartado
IDEAM horario (datos.gov.co)Mediciones in situ de la fuente oficial, con resolución horaria (permite estudiar el ciclo diario, clave en la costa), 4 variables y 76 estaciones con coordenadasSeleccionado

Nos quedamos con el IDEAM porque es el que corresponde a la pregunta que queremos responder: viento medido en sitios concretos y con resolución horaria, que es la escala en la que se manifiesta la brisa costera. Al ser la fuente oficial, además, cualquiera puede verificar y repetir la descarga.

1.3 Fuente y licencia

Conjunto (IDEAM, datos.gov.co)EnlaceResolución original
Velocidad del Vientohttps://www.datos.gov.co/d/sgfv-3yp810 min / 2 min
Dirección del Vientohttps://www.datos.gov.co/d/kiw7-v9ta10 min / 2 min
Temperatura Ambiente del Airehttps://www.datos.gov.co/d/sbwg-7ju41 h
Presión Atmosféricahttps://www.datos.gov.co/d/62tk-nxj51 h
Catálogo Nacional de Estaciones del IDEAMhttps://www.datos.gov.co/d/hp9r-jxuu—

Descargamos los datos de los departamentos de Atlántico, Bolívar, Cesar, Córdoba, La Guajira, Magdalena y Sucre para los años 2020 a 2025, en un archivo CSV por variable y año (24 archivos, unos 6.4 GB). Los cinco conjuntos se publican bajo la licencia Creative Commons Atribución-CompartirIgual 4.0 Internacional (CC BY-SA 4.0), con atribución al Instituto de Hidrología, Meteorología y Estudios Ambientales (IDEAM) (https://creativecommons.org/licenses/by-sa/4.0/), como datos abiertos en el marco de la Ley 1712 de 2014. Por la cláusula de compartir igual, este documento se publica con la misma licencia.

La propia ficha del portal advierte que “los datos … no han sido validados por el IDEAM”: son lecturas crudas de sensores automáticos. Por eso dedicamos la sección 1.6 a revisar su calidad.

Panel estación-hora: 1,302,607 filas | 76 estaciones | 2020-01-01 a 2025-12-31
Loading...

1.4 Diccionario de variables

Loading...

El panel solo guarda las horas con una velocidad válida, porque es la variable que queremos predecir; por eso la velocidad aparece en el 100 % de las filas. Eso no quiere decir que no haya huecos en el tiempo (los analizamos en la sección 2.6.1), y los porcentajes de las demás variables se calculan sobre esas mismas filas.

1.5 Estructura y tamaño de la muestra

La unidad de observación es la estación-hora. Las lecturas originales, tomadas cada 10 minutos (o cada 2 en algunos sensores), se promedian por hora; la dirección se promedia como un vector, para que 359° y 1° den 0° y no 180°. El resultado es un panel espacio-temporal: varias estaciones con coordenadas, observadas cada hora.

Filas con las 4 variables: 961,860 | predictoras del modelo: 26 | n/p = 36,995
Rango de la variable objetivo: 0.00 a 21.07 m/s
Loading...

El panel tiene 76 estaciones con velocidad; 63 de ellas tienen en algún momento las cuatro variables, y el conjunto que usamos para modelar (casos completos, sección 2.0) queda en 62. Aunque las filas se cuentan por cientos de miles, la cantidad de información independiente es mucho menor: dentro de cada estación las horas consecutivas se parecen mucho (sección 2.6), y las estaciones cercanas también se parecen entre sí (sección 2.7). Por eso más adelante validamos por periodos y por estación, y no con particiones al azar.

1.6 Calidad de datos

Auditamos los 24 archivos crudos; el detalle por variable y año está en ideam_viento/reportes/. Este es el resumen:

Loading...
Estación-año excluidas por sensor defectuoso: 12
Lecturas auditadas (después de quitar duplicados y filas fuera del Caribe): 25,577,649
Loading...
Lecturas de velocidad fuera de `[0, 25] m/s`: 6,621; 95 % vienen de GALERAZAMBA  - AUT, MONGUI
Lecturas crudas de velocidad que eliminaría cada umbral (revisión sobre los archivos originales):
Loading...
Loading...

Las reglas de limpieza que aplicamos (en procesar_variable.py) son las siguientes:

ProblemaRegla
Duplicados de descarga (2024–2025)Conservamos la primera lectura de cada estación, sensor e instante. En el 99.96 % de los duplicados las lecturas son idénticas; solo 1 236 instantes (de 30 millones de lecturas) tienen valores distintos
Valores fuera del rango de control→ NaN: velocidad [0, 25] m/s, temperatura [3, 45] °C, presión [500, 1100] hPa. Son umbrales de control de calidad pensados para esta red, no límites físicos universales (ver la justificación más abajo)
Sensor defectuosoEstación-año excluida si > 0.5 % de lecturas fuera de rango (en temperatura, solo lecturas > 45 °C)
Sensor pegadoMismo valor ≠ 0 durante ≥ 6 h (12 h en presión), o 0 durante ≥ 24 h → NaN
Picos de presiónA más de 30 hPa de la mediana de su estación-año → NaN
Presión incompatible con la altitudMediana a > 50 hPa de la presión estándar para la altitud del catálogo → estación-año descartada
Horas incompletasUna hora es válida si tiene al menos el 50 % de las lecturas esperadas

Los archivos los fuimos descargando y revisando por etapas, de modo que cada umbral se fijó conociendo solo una parte de los años. Lo resumimos en la tabla siguiente, porque importa saber si alguno se eligió mirando el periodo que después usamos como prueba (2025):

UmbralDatos conocidos al fijarlo¿Se conocía 2025?
Velocidad: rango [0, 25] m/s, 0.5 % para sensor defectuoso, tramo pegado 6 h (0 durante 24 h)Solo 2020No
Dirección: rango [0, 360]°, mismos plazos que la velocidad2020–2021No
Presión: rango [500, 1100] hPa, picos a > 30 hPa, tramo pegado 12 h, 50 hPa frente a la altitud2020–2023No
Temperatura: rango [3, 45] °C y tramo pegado 6 h2020–2022No
Temperatura: el criterio de sensor defectuoso cuenta solo lecturas > 45 °C (los 0 °C sueltos solo se enmascaran)2020–2025Sí, pero solo se usa en la depuración del análisis exploratorio
Hora válida con ≥ 50 % de lecturas; ventana de 30 días y mínimo de 100 lecturas (limpieza causal, sección 3)Fijados a priori, sin ajustarlos a los resultadosNo

El único criterio que fijamos después de ver 2025 es el de sensor defectuoso de la temperatura, y solo interviene en la depuración que usa el análisis exploratorio. Para el modelado (sección 3) usamos el criterio general, fijado antes (cualquier lectura fuera de [3, 45] °C cuenta), y en la sección 3.6 comprobamos que con el otro criterio el resultado prácticamente no cambia.

Algunos umbrales se definieron con datos de 2020–2023; por ello, reservamos 2024 para seleccionar la configuración del modelo, mediante una validación cruzada de cuatro pliegues dentro de ese año (sección 3.1), un año que, igual que 2025, no se usó para fijar ningún umbral. Los pliegues de 2021 a 2023 aparecen solo como referencia, y la curva de aprendizaje también se valida en 2024.

Para justificar los umbrales no basta con mirar los datos ya limpios, así que revisamos directamente en los CSV crudos las lecturas que cada umbral elimina (scripts/revisar_umbral.py, tabla de la celda siguiente):

  • Casi todas las lecturas de velocidad por encima de 25 m/s vienen de dos sensores con fallas evidentes, Galerazamba y Mongui, que además presentan saltos bruscos y meses enteros marcando 0.

  • En el resto de las estaciones, el 93 % de las lecturas eliminadas tiene la lectura anterior y la siguiente a no más de dos intervalos de muestreo, y el 59 % son picos aislados: superan en más de 15 m/s a la mediana de esas dos vecinas. Un salto de ese tamaño que aparece y desaparece en pocos minutos apunta a una falla del sensor, aunque no lo prueba; el resto de las lecturas no lo pudimos clasificar con certeza.

  • Entre un umbral de 25 y uno de 30 m/s la diferencia es de unas 70 lecturas crudas fuera de los sensores dañados. No evaluamos cómo cambiarían el panel y las métricas con otro umbral.

  • En temperatura, las lecturas por encima de 45 °C se concentran en sensores que repiten exactamente el mismo valor máximo, 50.0 °C. Eso parece el tope del instrumento más que una temperatura real, pero no pudimos confirmarlo con la ficha técnica, así que lo tratamos como un supuesto.

La presión ofrece una comprobación adicional: la medida coincide con la esperada para la altitud del catálogo (atmósfera estándar) con un error mediano de unos 3 hPa, lo que respalda tanto los datos como su conversión (los valores vienen escritos como "1.003,4"). Usamos esa misma relación para descartar una estación-año (El Guamo 2021, con 609 hPa a 75 m de altitud), así que para ella la comprobación no es independiente, pero sí lo es para las otras 280 estación-años.

Varias de estas reglas miran la estación-año completa: la mediana anual para detectar picos de presión, la proporción anual de lecturas anómalas para excluir un sensor, la detección del tramo pegado completo (que borra sus lecturas desde el inicio), la frecuencia de muestreo estimada con todo el archivo y la elección del sensor con más horas en el año. Es un control de calidad razonable para un archivo histórico, pero no reproduce lo que se sabría en el momento de pronosticar. La celda siguiente cuantifica cuántas lecturas afectan las dos reglas medibles (exclusión de estación-años y tramos pegados o picos); la elección del sensor y la frecuencia de muestreo no se pueden medir de la misma forma. Esta depuración la usamos solo para el análisis exploratorio. Para el modelado reconstruimos el procesamiento desde los CSV originales con reglas causales, en las que cada lectura se limpia únicamente con información anterior a ella (sección 3), y en la sección 3.6 comparamos los dos procesamientos.

Casi-duplicados. Además de los duplicados exactos, buscamos estaciones con las mismas coordenadas, que podrían ser la misma serie registrada con dos códigos distintos.

Coordenadas (9.3164, -75.3875): UNISUCRE [0025025270], PUERTA ROJA - AUT [0025025350]
  horas con dato: {'0025025270': 17286, '0025025350': 6013} | no comparten horas: se registraron en periodos distintos

1.6.1 Valores faltantes: patrón y mecanismo

<Figure size 1760x660 with 4 Axes>
Loading...

Los faltantes no son completamente aleatorios (MCAR). En buena parte son estructurales: el 68 % de los faltantes de presión, el 50 % de los de dirección y el 19 % de los de temperatura corresponden a estaciones que prácticamente no tienen ese sensor, y en el mapa de calor aparecen como franjas horizontales completas. Además, la distribución de la velocidad cambia según falte o no la otra variable (la prueba KS es significativa), sobre todo con la dirección: cuando falta, la velocidad media es de 1.32 m/s frente a 1.95 m/s, porque con calma la veleta no registra una dirección definida.

Lo más plausible es un mecanismo MAR, en el que la ausencia depende de variables que sí observamos (la estación y la velocidad). No podemos descartar que también dependa del propio valor faltante (MNAR); por ejemplo, un termómetro podría fallar más con calor extremo. La prueba de Little no es adecuada para series tan autocorrelacionadas, y con tantos datos la prueba KS siempre resulta significativa, así que nos fijamos en el tamaño del efecto: pequeño para la temperatura (0.04) y la presión (0.07) y moderado para la dirección (0.25). Con esto decidimos trabajar con casos completos, entendiendo que el modelo describe las estaciones y horas que tienen las cuatro variables (sección 2.9).

1.6.2 Sesgos de muestreo y representatividad

<Figure size 1540x440 with 2 Axes>
Horas de datos por departamento (%):
depto
LA GUAJIRA   18.300
MAGDALENA    17.300
BOLIVAR      16.400
CESAR        16.400
CORDOBA      11.800
ATLANTICO    10.700
SUCRE         9.000

La red cubre los siete departamentos de manera bastante pareja (entre el 9 % y el 18 % de las horas cada uno), pero está sesgada hacia las zonas bajas: la mediana de altitud es de 75 m y solo unas pocas estaciones están en la Sierra Nevada o en el Perijá. La red también cambia de un año a otro (entre 47 y 66 estaciones), y 2025 tiene casi el doble de estación-horas que 2023. Los resultados describen, por tanto, sobre todo el viento de las tierras bajas del Caribe, y conviene medir también cómo se comporta el modelo en estaciones que no participaron en su ajuste.

1.6.3 Consideraciones éticas

Los datos son mediciones ambientales de estaciones públicas: no contienen información personal ni permiten identificar a nadie, y las coordenadas corresponden a infraestructura que el IDEAM ya publica. El riesgo principal está en el uso. Como los datos no están validados oficialmente, no deberían servir como evidencia jurídica ni para tomar decisiones de seguridad sin una validación adicional, tal como advierte la propia fuente.


2. Análisis exploratorio de datos

2.0 Reserva del conjunto de prueba y construcción del conjunto de modelado

Antes de tomar cualquier decisión de modelado apartamos el año 2025 completo como conjunto de prueba. La sección 1 describe todo el periodo, incluido 2025, pero solo con fines descriptivos y de control de calidad; a partir de aquí el análisis exploratorio y todas las decisiones de modelado (predictoras, transformaciones e hiperparámetros) usan únicamente 2020–2024. La lista de vecinos del rezago espacial se define con las coordenadas del catálogo, que son metadatos estáticos. La partición es cronológica porque lo que queremos es pronosticar el futuro (sección 2.6).

Las predictoras se construyen estación por estación sobre una rejilla horaria completa, de modo que un hueco queda como NaN en lugar de tomar otra fecha, y usan solo horas completas hasta t, que es lo que se conoce al emitir el pronóstico en t + 1 h. Construirlas no requiere ajustar nada con los datos.

Entrenamiento (EDA): 946,851 estación-horas 2020–2024 | prueba reservada: 355,756 estación-horas 2025
Conjunto de modelado (casos completos): 611,727 filas | 62 estaciones
  705 filas de las últimas 24 h de 2024 quedan fuera de ambos conjuntos: su predictora es de 2024 pero su objetivo cae en 2025 (actúan como separación entre entrenamiento y prueba)
  entrenamiento: 400,163 filas (2020-01-02 a 2024-12-31)
  prueba:        210,859 filas (2025-01-01 a 2025-12-31)

2.1 Análisis de la variable objetivo

count   946851.000
mean         1.954
std          1.508
min          0.000
1%           0.163
5%           0.400
25%          0.867
50%          1.500
75%          2.613
95%          5.083
99%          6.933
max         21.067
Asimetría: 1.568 | curtosis (exceso): 3.327 | horas con 0 m/s: 0.42 %
λ de Yeo-Johnson: -0.425 (1 = sin transformación, 0 ≈ logaritmo)
<Figure size 1760x440 with 3 Axes>
<Figure size 1870x440 with 4 Axes>

La velocidad tiene asimetría positiva (1.57) y colas moderadas (curtosis de exceso de 3.3): la mediana es de 1.5 m/s, pero el 1 % de las horas supera los 6.9 m/s. Las calmas exactas son raras (0.4 % de las horas en 0 m/s). El λ = −0.43 de Yeo-Johnson sugiere que un logaritmo haría más simétrica la distribución; si eso mejora o no el pronóstico lo decide la validación cruzada (sección 3.1).

En los gráficos se ven tres fuentes claras de variación: un ciclo diario fuerte, con el mínimo hacia las 5 h y el máximo hacia las 14 h (la brisa diurna); un ciclo anual, con más viento de diciembre a marzo, en la temporada seca de los alisios; y diferencias fijas entre estaciones, porque La Guajira, al noreste, supera los 4–5 m/s de media, mientras que el interior de Córdoba y Bolívar ronda 1 m/s. De aquí salen dos consecuencias para el modelado: las métricas deben calcularse también por estación, porque el R² global se infla con esas diferencias fijas, y los ciclos diario y anual deben entrar como predictoras.

2.2 Análisis unidimensional

Loading...
<Figure size 1760x880 with 6 Axes>
Dirección media vectorial: 57° | longitud del vector medio: 0.06
Loading...

Ninguna variable sigue una distribución normal. Con tantos datos las pruebas de normalidad siempre rechazan, pero la asimetría y la curtosis apuntan en la misma dirección. La presión es bimodal y muy asimétrica (−3.5) porque mezcla estaciones costeras (≈ 1010 hPa) con estaciones de montaña (≈ 780 hPa); sus “atípicos” por IQR (10 %) no son errores sino altitud, y por eso la usamos junto con la altitud y como tendencia (su cambio en 3 y en 24 h). La constancia de la dirección se concentra cerca de 1 (dirección estable dentro de la hora), con una cola de horas de viento variable.

La dirección es circular, así que su media aritmética no tiene sentido. La rosa de vientos muestra que predominan los vientos del noreste y del este, los alisios, que además son los más fuertes. Como la red mezcla regímenes opuestos, el vector medio global es casi nulo (0.06), y la dirección tiene que tratarse por estación y en forma de componentes u/w. Entre las variables categóricas, “Sinóptica Secundaria” tiene una sola estación y “Pluviométrica” y “Agrometeorológica” cuatro cada una; son categorías tan raras que no usamos la categoría de la estación como predictora.

2.3 Análisis bidimensional

2.3.1 Numéricas vs. numéricas

<Figure size 1650x660 with 2 Axes>
<Figure size 1870x495 with 3 Axes>

2.3.2 Categóricas vs. numéricas y categóricas vs. categóricas

Con tantos datos casi cualquier diferencia resulta significativa, así que reportamos también tamaños de efecto (ε² de Kruskal-Wallis y V de Cramér) y corregimos por comparaciones múltiples con el método de Holm. Las pruebas se hacen por estación (n ≈ 70), para no inflar la significancia con horas autocorrelacionadas.

Loading...
Departamento × categoría (por estación): χ² = 24.0, gl = 30, p = 0.774, V de Cramér = 0.25
Loading...

2.3.3 Predictoras vs. variable objetivo y multicolinealidad

Loading...
<Figure size 1320x1100 with 2 Axes>

La velocidad se asocia con la temperatura, porque las horas más cálidas son también las más ventosas por el ciclo diario, y con la dirección. Con la presión la correlación agregada es casi nula, ya que la presión refleja sobre todo la altitud de cada estación.

Entre grupos, y después de la corrección de Holm, solo el departamento se asocia de forma significativa con la velocidad media de la estación, con un efecto grande (ε² = 0.31) que refleja el gradiente que va de La Guajira, al noreste, hacia el suroeste. El departamento y la categoría de la estación son independientes (p = 0.77).

Frente al objetivo, las predictoras más informativas son la velocidad actual y sus rezagos de 1 a 3 h y de 23 h (Spearman entre 0.65 y 0.76; información mutua entre 0.34 y 0.50). Las componentes u/w y la altitud tienen una información mutua alta pero una correlación baja, lo que indica una relación no lineal que un modelo lineal no aprovecha del todo. La temperatura, la presión y el calendario aportan poco por separado.

Los rezagos de velocidad (VIF entre 5 y 24) y el par altitud–presión (VIF ≈ 56) son muy redundantes. Eso no impide predecir, pero obliga a interpretar los coeficientes con cautela y justifica usar un modelo regularizado.

2.4 Análisis multivariado

<Figure size 1650x495 with 3 Axes>
Componentes para explicar el 90 % de la varianza: 14 de 26
Mahalanobis (χ² 99.9 %): 1.21 % de atípicos multivariados
Isolation Forest: 15.08 % | coincidencia con Mahalanobis entre los atípicos: 100 %
Perfil medio (z) de los atípicos de Mahalanobis:
vel               0.540
temp              0.150
pres             -0.190
dir_constancia   -3.340
Silueta por k: {2: 0.31, 3: 0.362, 4: 0.319, 5: 0.325, 6: 0.34} → k = 3
<Figure size 880x770 with 1 Axes>
Loading...

Hacen falta 14 de las 26 componentes principales para explicar el 90 % de la varianza. La primera recoge el “nivel de viento” (todos los rezagos de velocidad) y las siguientes separan, por un lado, la dirección y la época del año y, por otro, la altitud y la presión. Hay mucha redundancia dentro de cada grupo de variables, pero los grupos aportan información distinta entre sí.

Comparando cada hora con la climatología de su propia estación, el 1.2 % de las horas son atípicas según la distancia de Mahalanobis (umbral χ² al 99.9 %), y todas lo son también para Isolation Forest. Lo que tienen en común es una dirección muy variable dentro de la hora (la constancia está 3.3 desviaciones por debajo de lo normal) y algo más de viento: son horas de ráfagas o de cambio de régimen. Como se trata de fenómenos reales, no las eliminamos.

El k-means sobre el perfil de cada estación separa tres regímenes: 30 estaciones ventosas del norte y de la costa (2.8 m/s de media y un ciclo diario amplio), 33 estaciones de tierras bajas del interior con poco viento (1.3 m/s) y 7 estaciones de montaña (1 400 m de altitud y 20 °C). Estas diferencias estructurales son las que inflan el R² global.

2.5 Auditoría de fuga de datos

El pronóstico se emite en t + 1 h, cuando termina la hora t, para la hora que empieza en t + 24 h (sección 1.1). Todas las predictoras usan horas completas hasta t, también las de las estaciones vecinas:

PredictorasVentana¿Se conoce al emitir el pronóstico?
vel_l0 … vel_l23, vel_m24velocidad de t − 23 a tSí
u, w, u_m24, w_m24, dir_constanciadirección y velocidad hasta t (u, w: velocidad media × vector medio de dirección, una aproximación de las componentes medias del viento)Sí
temp, temp_d24, temp_amp24temperatura de t − 24 a tSí
pres, pres_d3, pres_d24presión de t − 24 a tSí
vel_vecinos, vel_vecinos_m24velocidad de las 4 estaciones más cercanas hasta tSí
hy_sin, hy_cos, doy_sin, doy_coshora y día del año del objetivoSí: el calendario es conocido de antemano
altitudcatálogoSí (estática)

Ninguna predictora se deriva del objetivo ni funciona como identificador de la estación. Como control adicional medimos el desempeño de cada predictora por separado, ajustada en 2020–2023 y evaluada en 2024, sin tocar la prueba; un valor cercano a 1 sería una señal de alarma.

Con una variable filtrada del futuro (velocidad de la hora t+23, anterior al objetivo): R² = 0.847
Loading...
Loading...

Ninguna predictora tiene un desempeño sospechoso por sí sola. La mejor, la velocidad actual, explica el 59 % de la variación en 2024, que es justamente lo que logra la persistencia. Para tener una referencia de cómo se vería una fuga, construimos a propósito una variable que no debería estar disponible: la velocidad de la hora t + 23, la anterior al objetivo. Sola alcanza un R² = 0.85.

No hay objetivos de entrenamiento dentro de 2025 ni filas duplicadas. El 92 % de las filas de prueba corresponde a estaciones que también están en el entrenamiento, lo cual es normal en un pronóstico temporal, donde se predice el futuro de estaciones conocidas; la generalización a estaciones nuevas la evaluamos aparte con GroupKFold. No descartamos ninguna variable por fuga; la categoría de la estación queda fuera por tener categorías demasiado raras (sección 2.2).

2.6 Componente temporal

2.6.1 Validación de la variable temporal

Zona horaria: la temperatura mediana es máxima a las 13 h y el viento a las 14 h. En hora local ambos máximos se esperan a primera hora de la tarde; si las marcas estuvieran en UTC aparecerían 5 h más tarde (18–20 h). Suponemos hora local de Colombia (UTC−5, sin horario de verano); la fuente no especifica la zona horaria.
Frecuencia: horaria regular
Marcas de tiempo duplicadas (estación, hora): 0
Huecos (> 1 h) dentro de cada estación: 22,337 | mediana 3 h | p90 19 h | máx 1563 días
<Figure size 1100x1320 with 2 Axes>

2.6.2 Serie completa, agregaciones y estacionalidad

<Figure size 1650x1100 with 3 Axes>

Cambios de régimen, eventos y calendario. Como la red cambia de un mes a otro, un promedio simple podría mostrar “cambios” que solo reflejan qué estaciones reportaron. Para evitarlo calculamos la anomalía de cada estación respecto a su propia climatología mensual (su media de ese mes en 2020–2024) y promediamos las anomalías de las estaciones presentes; así, una estación ventosa que entra o sale de la red no desplaza el promedio. Solo usamos meses con al menos 15 estaciones, y el gráfico muestra cuántas aporta cada mes.

Sobre esa serie aplicamos la prueba de Pettitt y marcamos los eventos ENSO del periodo según el Índice Oceánico El Niño (ONI) de la NOAA: La Niña, de mediados de 2020 a inicios de 2023, y El Niño, de mediados de 2023 a mediados de 2024. No analizamos los feriados por separado, porque el viento es una variable física y el día de la semana no muestra ningún efecto.

<Figure size 1650x605 with 2 Axes>
Meses analizados: 42 | estaciones por mes: 15 a 46 | estaciones presentes en todos esos meses: 1
Pettitt: cambio más probable en 2022-02 (p = 0.003); anomalía media antes +0.04 m/s y después -0.05 m/s
Anomalía media por fase ENSO (m/s): {'El Niño': 0.043, 'La Niña': -0.01, 'neutral': 0.014}

Con las anomalías por estación, la prueba de Pettitt señala un cambio en febrero de 2022 (p = 0.003), pero de un tamaño despreciable: la anomalía media pasa de +0.04 m/s a −0.05 m/s. Las diferencias entre las fases de ENSO también son mínimas (−0.01 m/s en La Niña y +0.04 m/s en El Niño). Al promediar directamente la velocidad de toda la red aparece un cambio de +0.3 m/s en abril de 2023, que coincide con el paso de La Niña a El Niño; ese cambio desaparece al controlar la composición de la red, de modo que se debe sobre todo a qué estaciones reportaban cada mes.

Hay dos advertencias: solo 42 de los 60 meses tienen al menos 15 estaciones (y solo una estación aparece en todos ellos), y una estación que reporta solo parte del periodo absorbe en su propia climatología parte de la variación entre años. Con estos datos, entonces, no podemos afirmar ni descartar un efecto de ENSO. Para el modelado, no vemos un cambio de régimen que obligue a tratar los años por separado, y la variación entre años queda cubierta por la validación por periodos.

2.6.3 Descomposición, estacionariedad y dependencia temporal

Usamos como ejemplo la estación con mejor cobertura en 2020–2024 y aplicamos las pruebas de estacionariedad a todas las estaciones con al menos un año continuo de datos diarios.

<Figure size 1540x880 with 4 Axes>
Fuerza de la estacionalidad anual: 0.94 | fuerza de la tendencia: 0.00
Fuerza del ciclo diario (60 días horarios): 0.83
Estaciones con ≥ 365 días continuos: 18
Loading...
<Figure size 1650x440 with 2 Axes>
<Figure size 1870x440 with 3 Axes>

2.6.4 Deriva temporal y heterogeneidad entre estaciones

Loading...
t
2020   0.761
2021   0.759
2022   0.885
2023   0.838
2024   0.771
<Figure size 1540x440 with 2 Axes>

La frecuencia es horaria y regular, sin marcas de tiempo duplicadas. La fuente no indica la zona horaria, pero el ciclo diario de la temperatura y del viento solo tiene sentido en hora local, así que trabajamos con ese supuesto. Hay unos 22 000 huecos, casi todos cortos (la mediana es de 3 h), aunque algunas estaciones dejan de reportar durante meses o años; por eso los rezagos se construyen sobre la rejilla horaria real, donde un hueco queda como NaN y nunca se toma otra fecha en su lugar.

En la estación de ejemplo, el ciclo diario explica el 83 % de la variación horaria sin tendencia y el ciclo anual el 94 % de la variación diaria, mientras que la tendencia en 2020–2024 es nula. El día de la semana no influye, como cabe esperar de una variable física.

En las series diarias originales, KPSS rechaza la estacionariedad en todas las estaciones analizadas y ADF solo la respalda en un tercio: la media cambia con la temporada. Una vez quitado el ciclo anual, ADF rechaza la raíz unitaria en el 100 % de las estaciones y KPSS no rechaza la estacionariedad en el 67 %. Las series parecen, por tanto, estacionarias alrededor de su ciclo estacional, aunque la prueba solo cubre las 18 estaciones con al menos un año continuo. Esto respalda incluir el día del año como predictora.

La ACF oscila con un periodo de 24 h y la PACF tiene picos en 1 h y alrededor de 24 h. La correlación entre la velocidad actual y la velocidad k horas después (calculada por fecha exacta) baja hasta k ≈ 12 h y vuelve a subir en k = 24 h: para pronosticar a un día, lo más informativo es la velocidad de hoy a la misma hora y la de las horas previas. La componente u (viento del este) y la velocidad de los vecinos mantienen una correlación estable con el viento futuro.

Los cambios de distribución entre años son pequeños (KS ≤ 0.14); los mayores aparecen en la presión y la temperatura en 2023–2024, cuando cambió la red de estaciones. La relación entre la velocidad de hoy y la de mañana también varía entre años (r entre 0.76 y 0.89), una forma leve de concept drift que la validación por periodos permite medir. Por último, las estaciones son muy distintas entre sí: la velocidad media va de menos de 1 a más de 5 m/s, y la amplitud del ciclo diario de menos de 0.5 a más de 3 m/s.

2.7 Componente espacial

2.7.1 Validación de coordenadas

Sistema de referencia: EPSG:4326 (WGS84, grados), el del catálogo del IDEAM
Latitud: 7.475 a 12.339 | longitud: -76.224 a -71.211
Coordenadas fuera de rango válido: 0 | (0, 0): 0 | posibles lat/lon invertidas: 0
Estaciones con coordenadas duplicadas: 1
Caja envolvente de las estaciones: lat 7.47–12.34 °N, lon -76.22–-71.21 °. Estaciones con departamento fuera de los 7 seleccionados: 0.
Estaciones al sur de 8 °N (sur de Bolívar y Córdoba, dentro de los departamentos): 4 — COLEGIO COOPERATIVO (BOLIVAR), CANELOS  - AUT (BOLIVAR), PUERTO LIBERTADOR (CORDOBA), JUAN JOSE - AUT (CORDOBA)

2.7.2 Mapas, patrón de puntos y cobertura

Distancia al vecino más cercano: mediana 25.6 km, máx 77.5 km
Índice de Clark-Evans R = 1.16 (R < 1 agrupado, R ≈ 1 aleatorio, R > 1 regular) | área de estudio ≈ 154,748 km²
Ripley: radios donde la curva observada sale de la envolvente CSR: ninguno
DBSCAN (eps = 40 km, mínimo 3 estaciones): 7 clusters; 21 estaciones aisladas (ruido)
<Figure size 1760x550 with 2 Axes>
<Figure size 2200x715 with 6 Axes>
Mapa base: límites departamentales de geoBoundaries (fuente OpenStreetMap, licencia ODbL 1.0).
Velocidad media por departamento (m/s): {'LA GUAJIRA': 3.26, 'ATLANTICO': 2.38, 'BOLIVAR': 1.75, 'CESAR': 1.63, 'MAGDALENA': 1.53, 'CORDOBA': 1.44, 'SUCRE': 1.42}

2.7.3 Autocorrelación espacial

Como matriz de pesos usamos los 4 vecinos más cercanos, estandarizada por filas. Preferimos k vecinos a una banda de distancia fija porque la densidad de estaciones es muy desigual y, con una banda, las estaciones aisladas de La Guajira quedarían sin vecinos.

I de Moran global (velocidad media por estación): I = 0.449, p = 0.001 (esperado sin estructura: -0.014)
Estaciones con p local < 0.05 sin corrección: 8 | con FDR < 0.05: 5
LISA
no significativo    69
alto-alto            5
<Figure size 1760x660 with 2 Axes>
Getis-Ord Gi* (FDR < 0.05): {'no significativo': 69, 'hotspot': 5}
Hotspots: AEROPUERTO PUERTO BOLIVAR  - AUT, SILLAMANA, TOROMANA - AUT, IPICHIRRAIN, PUERTO ESTRELLA - AUT
Efecto de la escala de agregación (MAUP): correlaciones con estaciones vs. con medias por departamento
Loading...

Todas las estaciones pertenecen a los siete departamentos seleccionados, y no hay coordenadas (0, 0) ni latitudes y longitudes invertidas. La caja envolvente llega hasta 7.5 °N porque el sur de Bolívar y de Córdoba se extiende por debajo de 8 °N. Dos estaciones comparten coordenadas, probablemente dos sensores del mismo sitio con códigos distintos, y las mantenemos como entidades separadas.

Sobre el mapa base se ve que casi todas las estaciones están en las tierras bajas y en la costa, con huecos en la Sierra Nevada, el interior de La Guajira y el sur de Bolívar. La coropleta pone a La Guajira muy por encima del resto, aunque un promedio por departamento mezcla sitios muy distintos, como costa y montaña; por eso el análisis se hace por estación (ver el efecto de la escala más abajo).

El índice de Clark-Evans sugiere un espaciamiento algo más regular que al azar (R = 1.16, sin prueba de significancia), con una mediana de 26 km hasta el vecino más cercano. La función L de Ripley, calculada con la misma ventana (el polígono convexo de las estaciones) para los datos y para las simulaciones, queda dentro de la envolvente de aleatoriedad espacial completa entre 5 y 150 km, así que a esas escalas no hay evidencia de agrupamiento ni de regularidad (el estimador no corrige el efecto de borde). DBSCAN, con distancia haversine y un radio de 40 km, encuentra 7 grupos de estaciones cercanas y deja 21 aisladas, sobre todo en el sur de Córdoba y Bolívar y en La Guajira, que son las zonas con menos cobertura.

La autocorrelación espacial es fuerte y significativa (I de Moran = 0.45, p = 0.001). Con corrección FDR por las múltiples pruebas locales, el LISA encuentra un único agrupamiento, el de valores altos en La Guajira (5 estaciones; 8 sin corregir), y Getis-Ord Gi* señala el mismo hotspot en el norte de La Guajira (Puerto Bolívar, Sillamana, Toromana, Ipichirrain y Puerto Estrella). Tomamos estos mapas locales como exploratorios. El semivariograma crece con la distancia y alcanza la varianza total hacia los 250 km: las estaciones a menos de unos 100 km tienen velocidades medias parecidas.

La escala de agregación también importa (el problema de la unidad de área modificable, MAUP): la correlación entre velocidad y temperatura cambia al pasar de estaciones a promedios por departamento (tabla anterior). Con solo siete departamentos las correlaciones agregadas son muy inestables y además mezclan costa y montaña, así que trabajamos siempre a escala de estación.

No usamos la latitud y la longitud crudas como predictoras: en un modelo lineal solo representarían un gradiente plano, y la información espacial ya entra por la altitud y por el rezago espacial. Tampoco usamos celdas H3 o geohash, porque con 76 estaciones casi todas las celdas tendrían una sola.

Como las estaciones vecinas se parecen, una validación al azar sería optimista. Por eso, además de GroupKFold por estación, en la sección 3.2 evaluamos bloques geográficos con una zona de separación, y usamos el promedio de los vecinos como predictora (rezago espacial).

2.8 Componente espacio-temporal

I de Moran: temporada seca 0.445 (p = 0.001) | temporada lluviosa 0.395 (p = 0.001)
Diferencia seca − lluviosa por estación: mediana 0.38 m/s; 82 % de las estaciones es más ventosa en la temporada seca
<Figure size 2090x605 with 4 Axes>

Diseño de la validación. Nuestro objetivo principal es pronosticar el futuro en estaciones conocidas, así que la validación principal es cronológica. Como objetivo secundario queremos saber cómo generaliza el modelo a estaciones que no participaron en su ajuste, y eso lo medimos con GroupKFold por estación. Ese escenario corresponde a una estación nueva de la red que ya tiene su propio historial y vecinos con sensores, no a un sitio sin mediciones, porque el modelo sigue usando la velocidad pasada de la estación y la de sus vecinos. Como GroupKFold no garantiza que las estaciones de prueba estén lejos de las de entrenamiento, agregamos un tercer esquema con bloques geográficos separados por una zona de amortiguación (sección 3.2). Reportamos los tres esquemas por separado.

El patrón espacial es estable entre temporadas (I de Moran de 0.45 en la seca y de 0.40 en la lluviosa): el hotspot de La Guajira no se desplaza, solo se intensifica. El 82 % de las estaciones tiene más viento en la temporada seca (mediana de +0.38 m/s). Las anomalías diarias de estaciones cercanas están correlacionadas (r ≈ 0.3–0.4 por debajo de 75 km) y la correlación decae con la distancia hasta ≈ 0.1 entre 300 y 400 km, porque los sistemas meteorológicos afectan a la vez a grupos de estaciones vecinas. Mezclar en el entrenamiento y en la prueba estaciones vecinas del mismo momento podría filtrar información; con la partición por años completos ese riesgo no existe.

2.9 Preprocesamiento

Todo lo que se ajusta con datos (el escalado y, si se usara, la transformación del objetivo) va dentro de un Pipeline que se ajusta solo con el entrenamiento. La tabla relaciona cada decisión con el hallazgo del análisis exploratorio que la motiva:

DecisiónHallazgo del EDA que la motiva
Partición cronológica (prueba = 2025) y validación cruzada con pliegues cronológicosDependencia temporal fuerte (2.6)
Validación adicional por estación (GroupKFold)Autocorrelación espacial y estaciones nuevas cada año (2.7, 2.6.1)
Rezagos de velocidad (1, 2, 3, 6, 12, 23 h) y media de 24 hACF/PACF con picos en 1 h y 24 h (2.6.3)
Hora del objetivo en seno/cosenoCiclo diario fuerte (2.1, 2.6.3)
Día del año en seno/cosenoCiclo anual: temporada seca-ventosa (2.1, 2.8)
Componentes u/w en vez de la dirección en gradosLa dirección es circular (2.2)
Tendencia de presión y cambio/amplitud de temperaturaCorrelación cruzada con rezago (2.6.3)
Rezago espacial (4 vecinos)I de Moran y correlación entre estaciones cercanas (2.7, 2.8)
AltitudDiferencias fijas entre estaciones (2.3, 2.4)
Casos completos (sin imputación)Los faltantes son sobre todo estructurales: estaciones sin el sensor (1.6.1)
Valores imposibles y sensores defectuosos → NaN o excluidosAuditoría de calidad (1.6)
Sin codificación categóricaLa categoría de la estación tiene categorías raras (2.2) y el departamento se asocia sobre todo con la ubicación, que ya entra por la altitud y el rezago espacial (2.3, 2.7)
Escalado estándar dentro del PipelineEl SVR es sensible a la escala; las variables tienen unidades distintas
Objetivo sin transformar (el logaritmo se probó en la validación cruzada y empeora el error)Asimetría positiva del objetivo (2.1)
Limpieza causal para el modeladoLa depuración del análisis exploratorio usa información de la estación-año completa (1.6)

3. Modelo base

Como modelo base usamos un SVR lineal (LinearSVR) dentro de un Pipeline con StandardScaler, para predecir y = vel(t + 24 h) con el pronóstico emitido en t + 1 h (sección 1.1). Con la pérdida cuadrática insensible a ε y ε = 0, la función de pérdida se reduce al error cuadrático con regularización L2, de modo que en la práctica se comporta como una regresión lineal regularizada, lo que además conviene por la fuerte colinealidad entre los rezagos (sección 2.3). Como referencias simples usamos un DummyRegressor (la media del entrenamiento), la persistencia de 24 h (vel(t), la misma hora del día anterior al objetivo) y la climatología de cada estación por mes y hora. Entrenamos con 2020–2024 y evaluamos en 2025, según la partición definida en la sección 2.0.

Datos del modelado: limpieza sin información futura. El análisis exploratorio usa la depuración de la sección 1.6, que mira la estación-año completa. Para que ninguna etapa del modelado use información del futuro, en esta sección trabajamos con un panel reprocesado desde los CSV originales con scripts/procesar_variable_causal.py (procesar_todo.py --causal), en el que cada lectura se limpia solo con lo ocurrido antes de ella o con metadatos estáticos del catálogo:

Regla retrospectiva (EDA, secciones 1–2)Regla causal (modelado, sección 3)
Excluir la estación-año si > 0.5 % de lecturas anómalasEnmascarar la lectura si en los 30 días anteriores el sensor tuvo > 0.5 % de lecturas anómalas (mínimo 100 lecturas)
Tramo pegado borrado desde su inicioSe enmascara desde que el tramo cumple el plazo de su variable (6 h; 12 h en presión; 24 h los ceros de velocidad y dirección); las lecturas previas se conservan
Picos de presión respecto a la mediana del añoRespecto a la mediana de los 30 días anteriores; sin historial, la presión estándar para la altitud del catálogo
Presión frente a la altitud con la mediana del añoCon la mediana de los 30 días anteriores
Frecuencia de muestreo estimada con el año completoMediana de los 144 intervalos anteriores del sensor; sin historial, la frecuencia nominal del tipo de sensor
Sensor con más horas en el añoSi hay varios sensores válidos en la hora, se promedian
Nombre y coordenadas de la última observaciónDe la primera observación

Las estaciones y los sensores nuevos no se descartan por falta de historial. Mientras un sensor no reúne al menos 100 lecturas en los 30 días anteriores no se lo puede marcar como defectuoso, y solo se le aplica el rango fijo; con sensores de 10 minutos eso ocurre en menos de un día, así que la regla puede empezar a actuar antes de cumplir un mes. Mientras tenga menos de 12 intervalos previos, la frecuencia de muestreo se toma de su tipo de sensor, y sin 3 días previos de presión la referencia es la presión esperada para su altitud.

Como la limpieza es causal en todos los años, tanto los pliegues de validación como la prueba usan datos limpiados solo con su pasado. Las predictoras se construyen con la misma función de la sección 2.0, y la lista de vecinos usa las coordenadas de la primera observación de cada estación. En la sección 3.6 comparamos este procesamiento con el original.

Panel causal: 1,308,726 estación-horas con velocidad (76 estaciones); 969,004 con las 4 variables
Conjunto de modelado causal: 616,854 filas | entrenamiento 402,200 | prueba 213,972 (53 estaciones) | 682 filas de separación en el cambio de año

3.1 Validación cruzada temporal en entrenamiento

Elegimos la configuración del modelo con cuatro pliegues cronológicos dentro de 2024. Como los umbrales de limpieza se fijaron con datos de hasta 2023 (sección 1.6), los datos de validación tienen que ser posteriores. Cada trimestre de 2024 se valida entrenando con todo lo anterior (2020–2023 y los trimestres previos de 2024), es decir, con una ventana que crece. Filtrar por la fecha del objetivo (el objetivo de entrenamiento siempre es anterior al inicio del trimestre) equivale a dejar una separación de 24 h, y el escalado se vuelve a ajustar dentro del Pipeline en cada entrenamiento. Nos quedamos con la configuración de menor RMSE medio en los cuatro trimestres.

Como referencia de estabilidad mostramos también pliegues por años completos, con validación en 2021, 2022, 2023 y 2024. No los usamos para elegir, porque los años 2021 a 2023 se conocían cuando fijamos algunos umbrales.

Configuración elegida (validación cruzada, 4 trimestres de 2024): log(1+y) = False, C = 0.01
Loading...
Referencia de estabilidad, pliegues por años completos (no se usan para elegir): la configuración de menor RMSE medio sería log(1+y) = False, C = 0.01
Loading...

3.2 Evaluación en el conjunto de prueba (2025)

Loading...
R² de la persistencia en prueba: IC 95 % [0.614, 0.679]
Loading...
Loading...
Loading...
El SVR supera a la persistencia en 94 % de las estaciones
<Figure size 1650x495 with 2 Axes>
Loading...

Bloques geográficos con zona de separación. Agrupamos las estaciones en 6 bloques contiguos (k-means sobre las coordenadas proyectadas). Cada bloque se usa como prueba en 2025, entrenando con 2020–2024 sin las estaciones del bloque ni las que están a menos de 30 km de alguna de ellas. Como el rezago espacial podría incluir estaciones del bloque de prueba, en este esquema usamos las predictoras sin rezago espacial (F_MET).

<Figure size 880x770 with 1 Axes>
Loading...
Predicciones negativas en prueba: 0 de 213,972 (0.00 %); mínimo 0.05 m/s
Loading...

Población cubierta. Exigir las cuatro variables deja fuera a las estaciones que no tienen sensor de presión o de temperatura. El modelo que solo usa la velocidad se puede evaluar sobre una población más amplia: todas las filas con los rezagos de velocidad completos.

Loading...

3.3 Diagnóstico de residuos

<Figure size 1870x495 with 3 Axes>
Asimetría: 0.73 | curtosis: 4.02 | Breusch-Pagan: LM = 1892, p = 0
<Figure size 1650x440 with 2 Axes>
ACF de residuos: rezago 1 = 0.65, rezago 24 = -0.10
I de Moran diario: media 0.212; significativo (p < 0.05) en 55 % de los días
I de Moran del residuo medio por estación: 0.286 (p = 0.002)

3.4 Curva de aprendizaje

Entrenamos con fracciones crecientes de 2020–2023, empezando por los datos más recientes, y evaluamos siempre en 2024, sin tocar la prueba.

<Figure size 880x440 with 1 Axes>
Loading...

3.5 Interpretación de coeficientes

<Figure size 990x770 with 1 Axes>
Loading...

Todos los resultados de esta sección usan la limpieza causal.

La configuración elegida con los cuatro trimestres de 2024 es la misma que se obtendría con los pliegues por años. El parámetro C no cambia el resultado, porque con unas 400 000 filas la regularización pesa muy poco. Transformar el objetivo con log(1 + y) empeora mucho el error: en los trimestres de 2024 la mejora media sobre la persistencia es de −0.2 %, frente a 12.8 % sin transformar, porque al volver a m/s con la exponencial los errores se amplifican. Por eso usamos el objetivo en su escala original.

En la prueba de 2025, el SVR completo obtiene R² = 0.737 (IC 95 %: 0.713–0.756) y RMSE = 0.733 m/s (0.710–0.758 m/s), frente a R² = 0.651 (0.614–0.679) de la persistencia. Es decir, reduce el error de la persistencia en un 13.2 % (IC 95 %: 12.2–14.4 %), y ese resultado se mantiene con bloques de 3, 7 o 14 días en el bootstrap. Mejora a la persistencia en el 94 % de las estaciones, y la climatología y el modelo de la media quedan muy por detrás.

En estaciones que no participaron en el ajuste (GroupKFold) la mejora media es del 13 %, con un R² medio de 0.65 entre pliegues. Con bloques geográficos separados por 30 km, y sin rezago espacial, la mejora media es del 12 % y es positiva en los seis bloques, entre el 6 % y el 17 %. El promedio de los R² de los bloques, que no es un R² calculado con todas las predicciones juntas, es de 0.57 y varía mucho de una región a otra (entre 0.30 y 0.73).

Casi toda la mejora viene de la historia de la velocidad (+12.3 %). En la comparación pareada con bootstrap, las variables meteorológicas reducen el RMSE en 0.007 m/s (IC 95 %: 0.006–0.008) y el rezago espacial en 0.001 m/s (0.001–0.002): diferencias que se distinguen de cero pero que en la práctica son despreciables. Los coeficientes respaldan este resultado: los mayores son la velocidad actual (0.43), la de hace 23 h (0.31) y la media de las últimas 24 h (0.27). En esencia, el modelo estima el viento de mañana a esta hora combinando el de hoy a la misma hora con el nivel general del día.

No hay predicciones negativas. El SVR mejora a la persistencia en todos los tramos por debajo de 6 m/s, pero con vientos fuertes (≥ 6 m/s, el 2 % de las horas) es peor que ella (RMSE de 1.75 m/s frente a 1.59 m/s) y los subestima en 1.3 m/s de media: el modelo lineal tiende hacia la media. Es una limitación importante para aplicaciones eólicas.

Al evaluar el modelo de solo velocidad sobre todas las filas con velocidad (310 027 filas y 65 estaciones en 2025, frente a 213 972 y 53 con las cuatro variables) se obtienen resultados agregados similares (R² = 0.74 y una mejora del 12 %), aunque eso no descarta diferencias en subgrupos concretos.

Los residuos tienen asimetría positiva y colas pesadas (curtosis de 4.0), son heterocedásticos (Breusch-Pagan, p ≈ 0: el error crece con la velocidad predicha), están fuertemente autocorrelacionados de una hora a la siguiente (0.65) y también en el espacio (I de Moran de 0.29 para el residuo medio por estación, significativo en el 55 % de los días). Queda estructura temporal y espacial que el modelo lineal no captura.

En la curva de aprendizaje, el error de validación deja de bajar a partir de unas 95 000 filas y el de entrenamiento no disminuye, lo que sugiere un sesgo alto, es decir, un modelo demasiado simple más que falta de datos. Hay que tomarlo con cautela, porque al ampliar la ventana cambian a la vez la cantidad de datos, los años y las estaciones incluidas.

3.6 Comparación con el procesamiento original y con el criterio alternativo de temperatura

Ajustamos el mismo modelo, con la misma configuración, sobre el panel de la depuración original y lo comparamos con el principal. Primero mostramos cada evaluación con su propia población de prueba, y después solo las observaciones comunes (misma estación, hora y valor objetivo), para distinguir un cambio de desempeño de un cambio en la población evaluada.

Loading...
Filas comunes: 209,506 (99.4 % de original y 97.9 % de causal); con el mismo objetivo: 86.3 %
Sobre esas 180,779 filas: RMSE(causal) − RMSE(original) = -0.0002 m/s (IC 95 %: -0.0003 a -0.0001)
Loading...

Criterio alternativo de temperatura. El modelado usa el criterio general de sensor defectuoso, fijado antes de conocer 2025 (cualquier lectura fuera de [3, 45] °C). Como prueba de sensibilidad reprocesamos la temperatura con el criterio de la depuración original, que se adoptó después de ver 2025 (contar solo las lecturas por encima de 45 °C), y repetimos el ajuste y la prueba.

Loading...
Filas comunes: 213,972 (99.2 % de criterio fijado viendo 2025 y 100.0 % de criterio principal); con el mismo objetivo: 100.0 %
Sobre esas 213,972 filas: RMSE(criterio principal) − RMSE(criterio fijado viendo 2025) = -0.0002 m/s (IC 95 %: -0.0003 a -0.0001)
Loading...

La limpieza causal evalúa 213 972 filas en 53 estaciones, frente a 210 859 en 51 con la original, porque ya no excluye estación-años completos, enmascara los tramos pegados solo desde que cumplen su plazo y promedia los sensores. Las métricas agregadas son casi iguales (R² = 0.737 frente a 0.739, con la misma mejora del 13.2 %). Sobre las 180 779 observaciones comunes con el mismo valor objetivo, la diferencia de RMSE es de −0.0002 m/s (IC 95 %: −0.0003 a −0.0001): distinguible de cero, pero de un tamaño despreciable. No encontramos, por tanto, una diferencia apreciable entre los dos procesamientos, y la pequeña diferencia en el R² agregado se explica por el cambio en la población evaluada. Con el criterio de temperatura adoptado después de ver 2025 las métricas son prácticamente idénticas (diferencia de RMSE de 0.0002 m/s sobre las mismas 213 972 filas), de modo que esa decisión no influye en los resultados que reportamos.

3.7 Robustez y alcance de los resultados

Un R² moderado no basta para descartar una fuga; lo que la descarta son la auditoría de las predictoras (2.5), la limpieza causal (3.6) y una partición que respeta el tiempo y se complementa con la validación por estación y por bloques geográficos (3.2). Lo que aporta el modelo es la reducción del error frente a la persistencia (3.5), no el valor absoluto del R², porque parte del R² global se debe a las diferencias fijas entre estaciones. El R² mediano por estación, entre 0.32 y 0.34, es la medida más fiel de lo que el modelo realmente pronostica, y deja un margen claro para mejorar.


4. Conclusiones y limitaciones

  1. A partir de 30 millones de lecturas crudas del IDEAM construimos un panel horario de 1.3 millones de estación-horas en 76 estaciones del Caribe colombiano (2020–2025), de las cuales 961 860 tienen las cuatro variables (63 estaciones). Documentamos la auditoría de calidad y comprobamos que la presión es coherente con la altitud del catálogo.

  2. El viento de la región tiene ciclos diario y anual fuertes, un gradiente espacial marcado, con un hotspot en La Guajira, y una dependencia temporal y espacial que obliga a validar por periodos y por estación.

  3. Con una limpieza que no usa información futura, el SVR lineal pronostica la velocidad a 24 h con R² = 0.737 y reduce el error de la persistencia en un 13.2 % (sección 3.5); la mejora se mantiene en estaciones que no participaron en el ajuste y en bloques geográficos separados. Las variables meteorológicas aportan poco a un modelo lineal, aunque su información mutua con el objetivo sugiere relaciones no lineales.

  4. Los residuos conservan estructura temporal, espacial y heterocedástica, y la curva de aprendizaje apunta a un sesgo alto. El paso siguiente es probar modelos no lineales (árboles y boosting) capaces de aprovechar interacciones como la de la dirección con la hora del día en la brisa marina.

Limitaciones. Los datos son crudos y no están validados por el IDEAM. La red cambia de un año a otro y está sesgada hacia las tierras bajas. Trabajamos con casos completos, así que quedan fuera las estaciones sin sensor de presión o de temperatura. El R² global depende del conjunto de estaciones de cada año, por lo que siempre lo acompañamos del R² por estación y de la mejora sobre la persistencia. El análisis exploratorio usa una depuración retrospectiva (1.6), distinta de la limpieza causal del modelado. La hora local es un supuesto que respalda el ciclo diario, pero la fuente no la documenta. Por último, la anticipación real desde que se emite el pronóstico es de 23 h hasta el inicio de la hora objetivo.

Versiones: {'numpy': '2.4.6', 'pandas': '3.0.6', 'sklearn': '1.9.1', 'scipy': '1.17.1', 'statsmodels': '0.15.0', 'matplotlib': '3.11.2', 'seaborn': '0.13.2'} | semilla: 42