
Detección y Visualización de Olas de Frío
Pipeline INMET → Relleno
→ Indicadores → Olas de Frío |
sus_climate_compute_coldwaves() y
sus_climate_plot_coldwaves()
Dr. Max Anjos
17 October, 2026
Source:vignettes/ondas_de_frio.Rmd
ondas_de_frio.RmdIntroducción
Las olas de frío son eventos climáticos extremos frecuentemente subestimados en la agenda de salud pública brasileña. Aunque Brasil es conocido por su clima cálido, el Sur y el Sudeste del país experimentan episodios periódicos de frío intenso asociados a la penetración de masas polares atlánticas, causando exceso de mortalidad cardiovascular y respiratoria — en especial entre personas mayores, niños y trabajadores al aire libre (Gasparrini et al., 2015; Huynen et al., 2001). Estudios globales estiman que el riesgo atribuible al frío supera al del calor en muchas regiones, incluso en zonas subtropicales (Gasparrini et al., 2015).
En Rio Grande do Sul, los frentes fríos polares pueden reducir la temperatura en 10–15 °C en menos de 24 horas durante el invierno austral (junio–agosto). En Porto Alegre, los episodios con temperaturas mínimas por debajo de 5 °C duran frecuentemente entre 5 y 10 días consecutivos, imponiendo una carga adicional sobre el sistema respiratorio y cardiovascular de poblaciones vulnerables. La ausencia de sistemas de vigilancia de olas de frío comparables a los de olas de calor contribuye a que este riesgo permanezca subdiagnosticado en los análisis del SUS.
El climasus4r implementa siete metodologías
internacionalmente reconocidas para la detección de olas de frío,
siguiendo la misma estructura de pipeline ya disponible para olas de
calor. Este tutorial demuestra el pipeline completo desde la descarga de
datos INMET hasta la visualización interactiva de los resultados,
utilizando la estación de Porto Alegre (A801) como caso de estudio.
Nota sobre reproducibilidad: Todo el pipeline es
determinista — dado el mismo período de datos INMET y los mismos
parámetros, los resultados son idénticos entre ejecuciones. Los bloques
de código marcados con eval = FALSE requieren conexión a
internet para la etapa de descarga (INMET) y pueden demorar algunos
minutos según el período solicitado.
¿Qué es una ola de frío?
Al igual que las olas de calor, las olas de frío se definen por dos componentes:
- Umbral de temperatura — la temperatura (o índice de confort térmico) debe caer por debajo de determinado valor crítico, típicamente definido como un percentil bajo de la distribución histórica (P10, P5) o como una desviación negativa fija respecto a la media climatológica. Mientras que las olas de calor usan la cola superior (P90), las olas de frío usan la cola inferior (P10).
- Duración mínima — la condición extrema debe persistir durante al menos N días consecutivos (comúnmente 3 o 5 días), distinguiendo eventos sostenidos de caídas de temperatura aisladas.
La ausencia de una definición universal refleja la variabilidad regional del clima y de los umbrales de tolerancia fisiológica. El criterio INMET para frío, por ejemplo, utiliza una desviación absoluta de −5 °C sobre la temperatura mínima histórica (Tmin − 5 °C), en lugar de la temperatura máxima utilizada en el criterio de olas de calor.
¿Por qué comparar métodos? En regiones subtropicales como Rio Grande do Sul, el método INMET — calibrado para la realidad climática nacional usando temperatura mínima — tiende a detectar eventos que percentiles genéricos pueden no capturar en años atípicamente fríos. El ECF (Excess Cold Factor, análogo al EHF para frío) es el único método que considera el factor de aclimatación: la misma temperatura mínima es fisiológicamente más estresante cuando ocurre después de un período relativamente cálido, pues el organismo no tuvo tiempo de adaptarse al frío. Comparar los siete métodos es una buena práctica de análisis de sensibilidad.
Visión general del pipeline
1. sus_climate_inmet() → 2. sus_climate_fill_inmet() → 3. sus_climate_compute_indicators() → 4. sus_climate_compute_coldwaves() → 5. sus_climate_plot_coldwaves()
Cada etapa recibe el producto de la anterior y añade información. La
función sus_climate_compute_coldwaves() espera datos
horarios con columnas estandarizadas de temperatura e
índices de confort térmico — exactamente lo que produce
sus_climate_compute_indicators().
Configuración del entorno
# Instalar climasus4r (GitHub) si es necesario
# install.packages("remotes")
# remotes::install_github("MaxAnjos/climasus4r")
library(climasus4r)
library(dplyr)Dependencias opcionales: Las funciones de
visualización requieren ggplot2, ggsci y
plotly. Para gráficos interactivos, instale también
htmlwidgets. La etapa de indicadores climáticos requiere
slider (ventanas deslizantes) y jsonlite.
install.packages(c("ggplot2", "ggsci", "plotly", "htmlwidgets", "slider", "jsonlite"))Etapa 1 — Adquisición de datos climáticos (INMET)
La red de estaciones INMET
El Instituto Nacional de Meteorologia (INMET) opera la mayor red de estaciones meteorológicas automáticas de Brasil, con cobertura en todos los estados. Los datos se ponen a disposición en formato CSV con resolución horaria e incluyen temperatura del aire (bulbo seco, máxima, mínima), humedad relativa, velocidad y dirección del viento, presión atmosférica y precipitación.
La función sus_climate_inmet() automatiza la descarga,
el parsing y la estandarización de estos archivos a un formato listo
para el análisis.
Parámetros principales
# Estrutura da chamada completa
df_inmet <- sus_climate_inmet(
years = 2020:2023, # Vetor de anos
uf = "", # UF (sigla) para filtrar estações
station_code = NULL, # Código(s) específico(s) de estação (opcional)
use_cache = TRUE, # Reutilizar arquivos já baixados
cache_dir = "~/.climasus4r_cache/climate",
parallel = FALSE, # TRUE habilita download paralelo via furrr/future
workers = NULL, # NULL = detectar automaticamente via parallelly
lang = "pt",
verbose = TRUE
)| Parámetro | Tipo | Descripción |
|---|---|---|
years |
entero o vector | Años a descargar (ej.: 2020:2023) |
uf |
character | Sigla del estado para filtrar estaciones (ej.: "RS",
"SC") |
station_code |
character | Código(s) específico(s) de estación INMET (ej.:
"A801") |
use_cache |
lógico | Si TRUE, reutiliza archivos ya descargados en
cache_dir
|
parallel |
lógico | Habilita descarga paralela vía
furrr/future (requiere múltiples núcleos) |
workers |
entero o NULL
|
Número de workers; NULL detecta automáticamente vía
parallelly
|
Ejemplo: estación de Porto Alegre (RS)
En este tutorial, utilizamos datos de la estación automática de Porto Alegre (código INMET A801), en Rio Grande do Sul — estado con el mayor registro histórico de olas de frío de Brasil. Porto Alegre, con latitud de aproximadamente −30°S, está sujeta a la penetración regular de masas polares atlánticas durante el invierno austral, convirtiéndola en un laboratorio natural para el estudio de eventos de frío extremo.
# Download de dados horários (2020–2023)
# A primeira execução pode levar alguns minutos; execuções subsequentes usam cache.
df_inmet <- sus_climate_inmet(
years = 2020:2023,
uf = "RS", # Porto Alegre - RS
use_cache = TRUE,
parallel = FALSE, # Use TRUE com workers = NULL em máquinas multicore
lang = "pt",
verbose = TRUE
)
# Inspecionar estrutura
glimpse(df_inmet)La salida es un data.frame con resolución horaria y
columnas estandarizadas por climasus4r:
#> Rows: ~35,064 (4 anos x 365 dias x 24 horas)
#> Columns: ~20
#>
#> $ date <POSIXct> 2020-01-01 00:00:00, 2020-01-01 01:00:00 ...
#> $ station_code <chr> 'A801', 'A801', ...
#> $ station_name <chr> 'PORTO ALEGRE', 'PORTO ALEGRE', ...
#> $ federal_unit <chr> 'RS', 'RS', ...
#> $ region <chr> 'Sul', 'Sul', ...
#> $ latitude <dbl> -30.05, -30.05, ...
#> $ longitude <dbl> -51.17, -51.17, ...
#> $ tair_dry_bulb_c <dbl> 14.2, 13.8, ...
#> $ tair_max_c <dbl> 16.1, 15.4, ...
#> $ tair_min_c <dbl> 12.5, 12.1, ...
#> $ rh_pct <dbl> 78.0, 80.0, ...
#> $ wind_speed_ms <dbl> 2.1, 1.8, ...
#> $ precip_mm <dbl> 0.0, 0.0, ...
Origen de los datos: Los datos brutos son los
archivos CSV disponibles públicamente por el INMET en
https://portal.inmet.gov.br/dadoshistoricos. El
climasus4r realiza el parsing automático de cada archivo
anual, aplica control de calidad y estandariza los nombres de columnas.
No se realiza ninguna interpolación o modificación de valores en esta
etapa.
Etapa 2 — Relleno de lagunas (gap-filling)
El problema de las lagunas en series horarias
Las estaciones automáticas del INMET frecuentemente presentan lagunas
causadas por fallas de transmisión, mantenimiento de equipos o eventos
climáticos extremos. La presencia de valores ausentes (NA)
en columnas de temperatura puede inviabilizar el cálculo de índices de
confort térmico y comprometer las estimaciones percentílicas utilizadas
en la detección de olas de frío.
La función sus_climate_fill_inmet() implementa un
relleno inteligente basado en modelos de regresión entrenados con
covariables meteorológicas correlacionadas (temperatura del aire,
humedad relativa, velocidad del viento, hora del día, estacionalidad).
El relleno se realiza variable por variable y respeta un umbral máximo
de lagunas (gap_percentage): si la proporción de valores
ausentes en determinada serie supera ese umbral, la estación se marca
como de baja calidad y no se aplica ningún relleno.
Parámetros principales
df_filled <- sus_climate_fill_inmet(
df = df_inmet,
target_var = "tair_dry_bulb_c", # Variável a preencher
datetime_col = NULL, # Detectado automaticamente
station_col = NULL, # Detectado automaticamente
quality_threshold = 0.4, # Máximo de NAs para aceitar a série (40%)
run_evaluation = FALSE, # Se TRUE: avalia métricas de ajuste
gap_percentage = 0.2, # Intervalo máximo de gap contínuo a preencher (20%)
keep_features = FALSE, # Manter covariáveis auxiliares no output
parallel = TRUE,
workers = NULL, # NULL = detectar automaticamente
verbose = TRUE,
lang = "pt"
)Relleno del conjunto completo
En la práctica, aplicamos el relleno a cada variable de temperatura y humedad relevante antes de calcular los indicadores de confort térmico:
# Preencher temperatura do ar (bulbo seco)
df_filled <- sus_climate_fill_inmet(
df = df_inmet,
target_var = "tair_dry_bulb_c",
lang = "pt",
verbose = TRUE
)
# Preencher temperatura máxima e mínima
df_filled <- sus_climate_fill_inmet(df_filled, target_var = "tair_max_c", lang = "pt")
df_filled <- sus_climate_fill_inmet(df_filled, target_var = "tair_min_c", lang = "pt")
# Preencher umidade relativa (necessária para UTCI, WBGT, HI)
df_filled <- sus_climate_fill_inmet(df_filled, target_var = "rh_pct", lang = "pt")
# Verificar proporção de NAs remanescentes
df_filled |>
summarise(
n_total = n(),
na_tmax = mean(is.na(tair_max_c)),
na_tmin = mean(is.na(tair_min_c)),
na_tair = mean(is.na(tair_dry_bulb_c)),
na_rh = mean(is.na(rh_pct))
)Buena práctica: Siempre aplique
sus_climate_fill_inmet() antes de
sus_climate_compute_coldwaves(). La función de detección
emite un aviso (cli_warn) si encuentra NAs en
las columnas de temperatura, pero no los rellena
automáticamente — esa decisión corresponde al analista, pues diferentes
estrategias de imputación pueden influir en los resultados.
Etapa 3 — Cálculo de indicadores climáticos
¿Por qué ir más allá de la temperatura del aire?
La temperatura del aire (bulbo seco) es la variable meteorológica más disponible, pero no es el mejor proxy para el estrés térmico humano en condiciones de frío. El cuerpo humano responde al ambiente frío resultante de la combinación de temperatura, humedad, velocidad del viento (factor de enfriamiento eólico) y radiación. Los índices de confort térmico integran estos factores y permiten estimar la percepción fisiológica del frío de forma más realista.
La función sus_climate_compute_indicators() calcula los
principales índices utilizados en las metodologías de detección de olas
de frío implementadas en climasus4r. Para olas de frío, el
interés recae sobre los valores mínimos diarios de
estos índices:
<div class="feature-icon">🌬️</div>
<h3>UTCI</h3>
<p><strong>Universal Thermal Climate Index.</strong> Modelo biometeorológico de referencia de la ISO 15743. Integra temperatura, humedad, viento y radiación en una temperatura equivalente fisiológica (°C). En frío extremo, un UTCI por debajo de −13 °C indica estrés frío fuerte.</p>
<div class="feature-icon">❄️</div>
<h3>WBGT</h3>
<p><strong>Wet Bulb Globe Temperature.</strong> Índice operacional ampliamente utilizado en salud ocupacional. En regímenes fríos, valores bajos de WBGT indican riesgo de hipotermia y lesiones por congelamiento en trabajadores al aire libre.</p>
<div class="feature-icon">🧊</div>
<h3>HI</h3>
<p><strong>Heat Index (Índice de Calor).</strong> Aunque fue concebido para el calor, valores bajos del HI mínimo diario pueden usarse como indicador de confort térmico precario en condiciones de frío y alta humedad.</p>
<div class="feature-icon">🌿</div>
<h3>PET</h3>
<p><strong>Physiological Equivalent Temperature.</strong> Temperatura de un ambiente de referencia con los mismos intercambios de calor del cuerpo. En valores negativos, indica malestar fisiológico intenso por frío.</p>
Llamada de la función
df_indicators <- sus_climate_compute_indicators(
df = df_filled,
indicators = "all", # Calcular todos os indicadores disponíveis
region = "auto", # Detectar região automaticamente por metadados
apply_validity_mask = TRUE, # Mascarar valores fora dos limites físicos
verify_physics = TRUE, # Verificar consistência física (Tmin <= Tmean <= Tmax)
keep_source_vars = TRUE, # Manter variáveis originais no output
verbose = TRUE,
lang = "pt"
)
# Verificar colunas adicionadas
names(df_indicators) |> grep("utci|wbgt|hi_c|pet", x = _, value = TRUE)Después de esta etapa, el data.frame contiene las
columnas adicionales necesarias para la detección de olas de frío por
los métodos UTCI, WBGT y HI:
| Columna nueva | Índice | Unidad |
|---|---|---|
utci_c |
UTCI | °C |
wbgt_c |
WBGT | °C |
hi_c |
Heat Index | °C |
pet_c |
PET | °C |
utci_c_flag_extreme |
Horas con UTCI > 38 °C | lógico |
wbgt_c_flag_extreme |
Horas con WBGT > 32 °C | lógico |
hi_c_flag_extreme |
Horas con HI > 51 °C | lógico |
Franjas frías del UTCI: La norma ISO 15743 define
categorías de estrés frío según el UTCI: sin estrés térmico (≥ 9 °C),
estrés frío leve (0–9 °C), estrés frío moderado (−13 a 0 °C), estrés
frío fuerte (−27 a −13 °C) y estrés frío muy fuerte (< −27 °C). En la
detección de olas de frío, el método UTCI en climasus4r
utiliza el UTCImin diario — el menor valor horario de
UTCI registrado ese día — comparado con el P10 histórico de ese mismo
indicador.
Etapa 4 — Detección de olas de frío
La función sus_climate_compute_coldwaves()
Esta es la función central del módulo de detección de frío de
climasus4r. Recibe datos horarios (producto de
sus_climate_compute_indicators()), los agrega a escala
diaria, calcula umbrales históricos percentílicos por estación del año
(usando una ventana deslizante de ±15 días alrededor de cada día del
año), aplica cada metodología de detección seleccionada y devuelve una
lista estructurada con tres componentes.
Firma completa
cw_result <- sus_climate_compute_coldwaves(
df = df_indicators, # Output de sus_climate_compute_indicators()
method = c("WHO", "WMO", "INMET", "EHF", "UTCI", "WBGT", "HI"),
baseline_start = "2020-01-01", # Início do período de referência
baseline_end = "2022-12-31", # Fim do período de referência
percentile = 10, # Percentil para limiares (P10 para cauda fria)
min_duration = NULL, # NULL = usar defaults por método
lang = "pt",
verbose = TRUE
)Nota sobre el argumento method = "EHF":
El identificador "EHF" se mantiene por consistencia con la
API de olas de calor, pero internamente la función aplica el algoritmo
del Excess Cold Factor (ECF) — el análogo frío del EHF.
El ECF fue propuesto por Nairn & Fawcett (2015) y adaptado aquí para
detectar eventos de frío extremo con base en la temperatura media diaria
y el factor de aclimatación.
Metodologías implementadas
La Tabla 1 presenta las siete metodologías implementadas, incluyendo la variable base, el criterio de umbral y la duración mínima predeterminada.
Tabla 1 — Metodologías de detección de olas de frío
implementadas en
sus_climate_compute_coldwaves()
| Método | Variable base | Criterio de umbral | Duración mínima | Referencia |
|---|---|---|---|---|
| WHO | Tmin diaria | Tmin < P10(Tmin) | 3 días | WMO & WHO (2015) |
| WMO | Tmin y Tmax diarias | Tmin < P10(Tmin) Y Tmax < P10(Tmax) | 5 días | Perkins & Alexander (2013) |
| INMET | Tmin diaria | Tmin < media histórica − 5 °C | 5 días | INMET (2009) |
| ECF | Tmean diaria | ECF > 0 (fórmula compuesta; ver abajo) | 3 días | Nairn & Fawcett (2015)* |
| UTCI | UTCImin diario | UTCImin < P10(UTCImin) | 3 días | ISO 15743 |
| WBGT | WBGTmin diario | WBGTmin < P10(WBGTmin) | 3 días | Liljegren et al. (2008) |
| HI | HImin diario | HImin < P10(HImin) | 3 días | Steadman (1979) |
*Adaptación para frío: ECF (Excess Cold Factor) en lugar de EHF (Excess Heat Factor).
Suavizado estacional de los percentiles: Para todos
los métodos basados en percentil, climasus4r utiliza una
ventana deslizante de ±15 días en torno a cada día del año (calculada
sobre el período de referencia), y no un percentil fijo calculado sobre
toda la serie. Este enfoque, recomendado por Fischer & Schär (2010),
elimina el sesgo estacional y garantiza que el mismo nivel de extremidad
relativa sea detectado en cualquier época del año. Para olas de frío, el
percentil se calcula en la cola inferior de la
distribución (P10), en oposición al P90 usado para olas de calor.
Fundamentos del Excess Cold Factor (ECF)
El ECF es el análogo frío del EHF (Nairn & Fawcett, 2015). Combina dos componentes que capturan, respectivamente, la magnitud absoluta del frío y el factor de aclimatación de la población:
Donde:
- ECI_sig (índice de significancia del frío): , mide cuánto la temperatura media de los últimos 3 días está por debajo del percentil 5 climatológico de la temperatura media. Valores positivos indican frío fisiológicamente relevante.
- ECI_acc (índice de aclimatación): , mide cuánto la temperatura media de los últimos 3 días está por debajo de la media de los 30 días anteriores. Es positivo cuando el período reciente es más frío que el mes anterior — es decir, el organismo estaba aclimatado al calor y fue expuesto repentinamente al frío, amplificando el estrés fisiológico.
El multiplicador garantiza que los eventos de frío que ocurren después de un período relativamente cálido reciban mayor peso — exactamente lo inverso de la lógica del EHF, donde el calentamiento súbito amplifica el riesgo de calor.
Los días con ECF > 0 se clasifican como días de ola de frío. La intensidad del evento se clasifica en tres categorías con base en el percentil 85 (ECF85) de todos los valores positivos de ECF observados en la estación:
- Baja Intensidad (LICW): 0 < ECF_peak < ECF85
- Severa (SCW): ECF85 ≤ ECF_peak < 3 × ECF85
- Extrema (ECW): ECF_peak ≥ 3 × ECF85
Método INMET: calibración para el frío en Brasil
El método INMET para frío define una ola de frío cuando la temperatura mínima diaria cae por debajo de la media climatológica de la temperatura mínima en al menos 5 °C durante 5 o más días consecutivos (INMET, 2009). A diferencia del criterio de olas de calor (que usa la temperatura máxima), el criterio de frío usa la temperatura mínima — la variable más sensible a la penetración de masas polares.
La media climatológica de la Tmin se calcula sobre el período de referencia definido por el usuario, utilizando la misma ventana deslizante de ±15 días usada en los percentiles. Este criterio es particularmente adecuado para el Sur de Brasil, donde los valores absolutos de Tmin ya son bajos y la vulnerabilidad a la mortalidad por frío está más asociada a la desviación respecto a la norma local que al valor absoluto.
Ejecutando la detección
Ejemplo 1: métodos basados en temperatura del aire
# Métodos que requerem apenas temperatura do ar (Tmax, Tmin, Tmean)
cw_temp <- sus_climate_compute_coldwaves(
df = df_indicators,
method = c("WHO", "WMO", "INMET", "EHF"),
baseline_start = "2020-01-01",
baseline_end = "2022-12-31",
percentile = 10,
lang = "pt",
verbose = TRUE
)Ejemplo 2: todos los métodos (incluyendo índices de confort)
# Todos os métodos — requer colunas utci_c, wbgt_c, hi_c
cw_all <- sus_climate_compute_coldwaves(
df = df_indicators,
method = "all", # Equivale a c("WHO","WMO","INMET","EHF","UTCI","WBGT","HI")
baseline_start = "2020-01-01",
baseline_end = "2022-12-31",
percentile = 10,
lang = "pt",
verbose = TRUE
)Ejemplo 3: criterio conservador
# Critério mais conservador: P5 e mínimo de 5 dias para todos os métodos
cw_strict <- sus_climate_compute_coldwaves(
df = df_indicators,
method = c("WHO", "INMET"),
baseline_start = "2020-01-01",
baseline_end = "2022-12-31",
percentile = 5, # Limiar mais restritivo → menos eventos, mais intensos
min_duration = 5, # Substitui os defaults por método
lang = "pt",
verbose = TRUE
)Análisis de sensibilidad: Se recomienda ejecutar la detección con diferentes combinaciones de percentil (P5, P10, P15) y duración mínima (3, 5, 7 días) y comparar el número de eventos detectados. Esto permite evaluar la robustez de los resultados epidemiológicos frente a las decisiones metodológicas.
Baseline corto en este tutorial: Este tutorial usa
solo 4 años de datos (2020–2023) para agilizar la descarga.
climasus4r emite un aviso cuando el baseline tiene menos de
20 años, lo cual es esperado aquí. Para investigación real, se
recomienda usar al menos 1981–2010 o 1991–2020 como período de
referencia climatológica.
Estructura del output
La función devuelve una lista con nombre con tres componentes — misma
estructura que el output de
sus_climate_compute_heatwaves(), pero con nomenclatura
adaptada para frío:
# Inspecionar o output
names(cw_all)
#> [1] "events" "daily" "summary"
$events — tabla de eventos
Un data.frame con una fila por evento de ola de frío
detectado. Cada fila representa un episodio continuo de días con la
condición de ola de frío activa para un determinado método y
estación.
# Primeiros eventos detectados
head(cw_all$events)| Columna | Tipo | Descripción |
|---|---|---|
event_id |
character | Identificador único:
<estación>_<método>_<N>
|
station_code |
character | Código INMET de la estación |
method |
character | Método de detección (WHO, WMO, etc.) |
start_date |
Date | Fecha de inicio del evento |
end_date |
Date | Fecha de fin del evento |
duration_days |
integer | Duración en días consecutivos |
temp_mean |
double | Temperatura media del período (variable del método) |
temp_peak |
double | Temperatura más fría del período (mínimo) |
anomaly_mean |
double | Anomalía media (umbral − temperatura; positivo = más frío que el umbral) |
anomaly_cumulative |
double | Anomalía acumulada a lo largo del evento |
severity_index |
double | Índice de severidad: duración × anomalía media |
ecf_peak |
double | Pico del ECF (solo método EHF/ECF; NA para otros) |
ecf_mean |
double | Media del ECF durante el evento (solo EHF/ECF) |
intensity_class |
character | Clasificación: LICW, SCW, ECW (solo EHF/ECF) |
region |
character | Región geográfica de la estación |
federal_unit |
character | UF de la estación |
Diferencias importantes respecto al output de olas de calor:
| Campo | Olas de Calor | Olas de Frío |
|---|---|---|
temp_peak |
Temperatura más cálida del evento | Temperatura más fría del evento |
anomaly_mean |
temp − umbral (positivo = más cálido) |
umbral − temp (positivo = más frío) |
| Flags diarios |
hw_who, hw_any, … |
cw_who, cw_any, … |
| Específico de ECF |
ehf_peak, ehf_mean
|
ecf_peak, ecf_mean
|
| Resumen anual | total_days_hw |
total_days_cw |
| Clases de intensidad | LIHW, SHW, EHW | LICW, SCW, ECW |
# Filtrar os 10 eventos mais severos pelo índice de severidade
cw_all$events |>
arrange(desc(severity_index)) |>
select(event_id, method, start_date, end_date, duration_days,
temp_peak, anomaly_mean, severity_index) |>
head(10)
# Contar eventos por método
cw_all$events |>
count(method, name = "n_eventos") |>
arrange(desc(n_eventos))
$daily — serie diaria con flags
El data.frame diario contiene una fila por estación por
día, con las variables agregadas y columnas lógicas
(TRUE/FALSE) indicando si ese día pertenece a
una ola de frío según cada método:
# Inspecionar colunas de flags
cw_all$daily |>
select(station_code, date_day, tmin, tmean, starts_with("cw_")) |>
head(10)La columna cw_any es TRUE si
cualquier método detectó ola de frío en ese día — útil
para análisis de exposición sin comprometerse con un único criterio.
# Dias com onda de frio ativa por pelo menos um método
cw_all$daily |>
filter(cw_any == TRUE) |>
select(date_day, tmin, tmean, cw_who, cw_inmet, cw_ehf, cw_utci) |>
head(20)
# Concordância entre métodos: proporção de dias classificados por cada um
cw_all$daily |>
summarise(
pct_who = mean(cw_who, na.rm = TRUE) * 100,
pct_wmo = mean(cw_wmo, na.rm = TRUE) * 100,
pct_inmet = mean(cw_inmet, na.rm = TRUE) * 100,
pct_ehf = mean(cw_ehf, na.rm = TRUE) * 100,
pct_utci = mean(cw_utci, na.rm = TRUE) * 100,
pct_wbgt = mean(cw_wbgt, na.rm = TRUE) * 100,
pct_hi = mean(cw_hi, na.rm = TRUE) * 100,
pct_any = mean(cw_any, na.rm = TRUE) * 100
)
$summary — resumen anual
El resumen anual agrega las estadísticas por estación, método y año, siendo el punto de entrada natural para análisis de tendencia temporal:
# Resumo anual
cw_all$summary |>
filter(method == "INMET") |>
select(year, station_code, n_events, total_days_cw,
mean_duration, max_duration, mean_anomaly, severity_total) |>
arrange(desc(year))| Columna | Descripción |
|---|---|
year |
Año |
station_code |
Código de la estación |
method |
Método de detección |
n_events |
Número de eventos en el año |
total_days_cw |
Total de días de ola de frío en el año |
mean_duration |
Duración media de los eventos (días) |
max_duration |
Duración del evento más largo (días) |
mean_intensity |
Temperatura media en los eventos |
max_intensity |
Temperatura de pico (más fría) en los eventos |
mean_anomaly |
Anomalía media en los eventos |
severity_total |
Suma de los índices de severidad de los eventos en el año |
Etapa 5 — Visualización de olas de frío
La función sus_climate_plot_coldwaves()
La visualización transforma el output estructurado de
sus_climate_compute_coldwaves() en gráficos interpretativos
con paleta de colores fríos (tonos de azul y violeta). La función ofrece
cuatro tipos de visualización, cada uno respondiendo a una pregunta
analítica diferente:
<div class="feature-icon">📅</div>
<h3>timeline</h3>
<p>Diagrama de Gantt que muestra la posición temporal, duración e intensidad de cada evento. Ideal para identificar episodios de frío prolongados en el invierno austral y comparar métodos.</p>
<div class="feature-icon">🗓️</div>
<h3>calendar</h3>
<p>Mapa de calor tipo calendario que muestra la ocurrencia diaria de olas de frío a lo largo de los meses. Revela la concentración estacional (invierno austral) y patrones interanuales asociados a La Niña.</p>
<div class="feature-icon">❄️</div>
<h3>intensity</h3>
<p>Dispersión duración × temperatura mínima de pico, con eje Y invertido (más frío = más alto). Distingue eventos largos de eventos con temperaturas extremadamente bajas.</p>
<div class="feature-icon">📈</div>
<h3>trend</h3>
<p>Barras agrupadas del número de eventos por año y método. Permite identificar variabilidad interanual y posibles tendencias en la frecuencia de olas de frío.</p>
Firma completa
p <- sus_climate_plot_coldwaves(
cw_result = cw_all, # Output de sus_climate_compute_coldwaves()
type = "timeline", # "timeline" | "calendar" | "intensity" | "trend"
station_code = NULL, # Filtrar por estação específica
method = NULL, # Filtrar por método (ex.: "INMET", "EHF")
year = NULL, # Filtrar por ano (útil para "calendar")
interactive = TRUE, # TRUE = plotly; FALSE = ggplot2 estático
color_palette = "npg", # Paleta ggsci: "npg", "lancet", "jama", etc.
lang = "pt", # "pt" | "en" | "es"
save_plot = NULL # Caminho para salvar (HTML ou PNG)
)| Parámetro | Opciones | Efecto |
|---|---|---|
type |
"timeline", "calendar",
"intensity", "trend"
|
Tipo de gráfico |
interactive |
TRUE (plotly), FALSE (ggplot2) |
Interactividad |
color_palette |
cualquier paleta del paquete ggsci
|
Esquema de colores (aplicado sobre paleta base de azules) |
lang |
"pt", "en", "es"
|
Idioma de las etiquetas |
save_plot |
ruta .html o .png
|
Guardar el gráfico en disco |
Gráfico 1: Línea del tiempo (timeline)
El gráfico de línea del tiempo presenta cada evento como un segmento horizontal (estilo Gantt), con espesor proporcional a la duración y color indicando la clase de intensidad ECF (para el método EHF/ECF; para otros métodos, los eventos se muestran en azul uniforme).
# Linha do tempo de todos os eventos — todos os métodos
sus_climate_plot_coldwaves(
cw_result = cw_all,
type = "timeline",
interactive = TRUE,
lang = "pt"
)
# Filtrar apenas eventos pelo método INMET
sus_climate_plot_coldwaves(
cw_result = cw_all,
type = "timeline",
method = "INMET",
interactive = TRUE,
lang = "pt"
)
# Versão estática para publicação
p_timeline <- sus_climate_plot_coldwaves(
cw_result = cw_all,
type = "timeline",
method = c("WHO", "INMET", "EHF"),
interactive = FALSE, # ggplot2 puro
color_palette = "lancet", # Paleta Lancet (jornais biomédicos)
lang = "pt",
save_plot = "timeline_ondas_frio.png" # Salvar em PNG
)
print(p_timeline)Interpretación: Los segmentos más largos indican eventos más duraderos; el espesor refuerza visualmente la duración. Observe la concentración de eventos entre junio y agosto (invierno austral). El método WMO (doble umbral: Tmin y Tmax < P10) tiende a generar menos eventos y de mayor duración que el WHO (solo Tmin), pues exige que tanto el día como la noche sean excepcionalmente fríos.
Gráfico 2: Calendario (calendar)
El calendario muestra cada día del año en celdas coloreadas — azul para días de ola de frío, gris para días normales. Es el gráfico más intuitivo para comunicar la estacionalidad de los eventos al público no técnico.
# Calendário para um ano específico — método WHO
sus_climate_plot_coldwaves(
cw_result = cw_all,
type = "calendar",
method = "WHO",
year = 2021,
interactive = TRUE,
lang = "pt"
)
# Calendário com cw_any (qualquer método) — todos os anos
sus_climate_plot_coldwaves(
cw_result = cw_all,
type = "calendar",
method = NULL, # NULL → usa cw_any (qualquer método)
interactive = FALSE,
lang = "pt"
)Interpretación: Observe la concentración de días de ola de frío en junio, julio y agosto en el Sur de Brasil. Los años con eventos La Niña (que tienden a intensificar los frentes fríos en el RS) presentan calendarios con más bloques azules consecutivos. Estos períodos merecen atención especial en el análisis de mortalidad respiratoria y cardiovascular en el SUS.
Gráfico 3: Intensidad vs. duración (intensity)
Este gráfico de dispersión posiciona cada evento en el plano
cartesiano duración × temperatura mínima de pico. El eje Y está
invertido (scale_y_reverse()), de modo que las
temperaturas más bajas (más frías, más extremas) aparecen en la parte
superior del gráfico — convención que hace intuitiva la interpretación:
cuanto más alto y a la derecha, mayor el riesgo epidemiológico.
# Intensidade ECF (com classificação LICW / SCW / ECW)
sus_climate_plot_coldwaves(
cw_result = cw_all,
type = "intensity",
method = "EHF", # "EHF" aciona o algoritmo ECF
interactive = TRUE,
lang = "pt"
)
# Todos os métodos juntos (sem classificação de intensidade ECF)
sus_climate_plot_coldwaves(
cw_result = cw_all,
type = "intensity",
method = NULL,
interactive = FALSE,
lang = "pt"
)Interpretación: Los eventos en el cuadrante superior derecho (larga duración + temperatura muy baja) son los más peligrosos desde el punto de vista de la salud pública. El ECF captura la sutileza de la aclimatación: un evento con Tmin de 5 °C tras un período de invierno consolidado es menos estresante que la misma temperatura ocurriendo inmediatamente después de días cálidos — exactamente lo que mide el componente ECI_acc.
Gráfico 4: Tendencia anual (trend)
El gráfico de tendencia muestra el número de eventos detectados por año para cada método, permitiendo evaluar la variabilidad interanual y posibles tendencias en la frecuencia de olas de frío a lo largo del período analizado.
# Tendência anual — todos os métodos
sus_climate_plot_coldwaves(
cw_result = cw_all,
type = "trend",
interactive = TRUE,
lang = "pt"
)
# Tendência apenas para WHO e INMET (comparação de sensibilidade)
sus_climate_plot_coldwaves(
cw_result = cw_all,
type = "trend",
method = c("WHO", "INMET"),
interactive = FALSE,
lang = "pt",
save_plot = "tendencia_ondas_frio.png"
)Interpretación: La variabilidad interanual de las olas de frío es grande y está fuertemente influenciada por el ENOS (El Niño-Oscilación del Sur): La Niña tiende a aumentar la frecuencia e intensidad de los frentes fríos en el Sur de Brasil. Compare los patrones entre métodos: el método INMET tiende a ser más restrictivo (exige una desviación de −5 °C sobre la Tmin histórica), mientras que los métodos percentílicos capturan la relatividad del evento respecto al histórico local.
Guardando gráficos
# Gráfico interativo → arquivo HTML autossuficiente
sus_climate_plot_coldwaves(
cw_result = cw_all,
type = "timeline",
interactive = TRUE,
lang = "pt",
save_plot = "ondas_frio_timeline.html"
)
# Gráfico estático → PNG de alta resolução (300 dpi)
sus_climate_plot_coldwaves(
cw_result = cw_all,
type = "trend",
interactive = FALSE,
lang = "pt",
save_plot = "ondas_frio_tendencia.png" # ggsave com dpi=300
)Análisis avanzado de los resultados
Integrando eventos al calendario epidemiológico
El componente $daily con la columna cw_any
puede cruzarse directamente con datos de mortalidad y morbilidad del SUS
para calcular el exceso de defunciones e internaciones durante olas de
frío:
# Exemplo conceitual: cruzamento com dados de mortalidade SIM
# (após completar o pipeline de importação dos dados SIM)
# 1. Preparar a série diária de mortalidade respiratória em idosos
# df_sim_diario <- sus_data_aggregate(df_sim, by = "day") |>
# filter(
# cid_grupo %in% c("J"), # Doenças respiratórias (CIDs J00-J99)
# idade >= 65 # Idosos - grupo mais vulnerável ao frio
# )
# 2. Adicionar flag de onda de frio
# df_analise <- df_sim_diario |>
# left_join(
# cw_all$daily |> select(date_day, cw_any, cw_inmet, tmin),
# by = c("date" = "date_day")
# )
# 3. Comparar mortalidade em dias com/sem onda de frio
# df_analise |>
# group_by(cw_any) |>
# summarise(
# n_dias = n(),
# obitos_medio = mean(n_obitos, na.rm = TRUE),
# sd = sd(n_obitos, na.rm = TRUE)
# )Análisis de concordancia entre métodos
# Proporção de dias classificados como onda de frio por N métodos simultaneamente
cw_all$daily |>
mutate(
n_methods = rowSums(
across(c(cw_who, cw_wmo, cw_inmet, cw_ehf, cw_utci, cw_wbgt, cw_hi)),
na.rm = TRUE
)
) |>
count(n_methods) |>
mutate(pct = round(n / sum(n) * 100, 1))El análisis de concordancia responde a una pregunta central de la epidemiología ambiental: ¿en cuántos de los días clasificados como ola de frío hay consenso entre los métodos? Una alta concordancia aumenta la confianza en los resultados; una baja concordancia sugiere que el impacto en salud puede variar significativamente según el criterio adoptado.
Referencias
Mortalidad por frío — epidemiología global
- Gasparrini, A., Guo, Y., Hashizume, M., Lavigne, E., Zanobetti, A., Schwartz, J., … & Armstrong, B. (2015). Mortality risk attributable to high and low ambient temperature: a multicountry observational study. The Lancet, 386(9991), 369–375. https://doi.org/10.1016/S0140-6736(14)62114-0
- Huynen, M.M.T.E., Martens, P., Schram, D., Weijenberg, M.P. & Kunst, A.E. (2001). The impact of heat waves and cold spells on mortality rates in the Dutch population. Environmental Health Perspectives, 109(5), 463–470.
- Basu, R. & Samet, J.M. (2002). Relation between elevated ambient temperature and mortality: a review of the epidemiologic evidence. Epidemiologic Reviews, 24(2), 190–202.
Contexto Brasil y Sur
- Braga, A.L.F., Zanobetti, A. & Schwartz, J. (2001). The time course of weather-related deaths. Epidemiology, 12(6), 662–667.
- Vasconcelos, J., Freire, E., Morais, J., Machado, J.R. & Santana, P. (2013). The health impacts of poor housing conditions and thermal discomfort. Procedia Environmental Sciences, 19, 107–112.
Conceptos generales y marco de percentiles
- Perkins, S.E. & Alexander, L.V. (2013). On the measurement of heat waves. Journal of Climate, 26(13), 4500–4517.
- Fischer, E.M. & Schär, C. (2010). Consistent geographical patterns of changes in high-impact European heatwaves. Nature Geoscience, 3, 398–403.
Métodos WHO y WMO (adaptados para frío)
- WMO & WHO (2015). Heatwaves and Health: Guidance on Warning-System Development. Organización Meteorológica Mundial, Ginebra.
- WMO (2021). Guidelines on the Definition and Monitoring of Extreme Weather and Climate Events. Organización Meteorológica Mundial.
Método INMET
- INMET — Instituto Nacional de Meteorologia (2009). Normais Climatológicas do Brasil 1961–1990. Brasília: MAPA/INMET.
ECF (Excess Cold Factor)
- Nairn, J.R. & Fawcett, R.J.B. (2015). The Excess Heat Factor: A metric for heatwave intensity and its use in classifying heatwave severity. International Journal of Environmental Research and Public Health, 12(1), 227–253. https://doi.org/10.3390/ijerph120100227
UTCI (Universal Thermal Climate Index) — régimen frío
- Broede, P., Fiala, D., Blazejczyk, K., Holmer, I., Jendritzky, G., Kampmann, B., Tinz, B. & Havenith, G. (2012). Deriving the operational procedure for the Universal Thermal Climate Index (UTCI). International Journal of Biometeorology, 56(3), 481–494. https://doi.org/10.1007/s00484-011-0454-1
- ISO 15743:2008. Ergonomics of the thermal environment — Cold workplaces: Risk assessment and management. Organización Internacional de Normalización.
WBGT (Wet Bulb Globe Temperature)
- Liljegren, J.C., Carhart, R.A., Lawday, P., Tschopp, S. & Sharp, R. (2008). Modeling the wet bulb globe temperature using standard meteorological measurements. Journal of Occupational and Environmental Hygiene, 5(10), 645–655.
HI (Heat Index)
- Steadman, R.G. (1979). The assessment of sultriness. Part I: A temperature-humidity index based on human physiology and clothing science. Journal of Applied Meteorology, 18(7), 861–873.
- Steadman, R.G. (1984). A universal scale of apparent temperature. Journal of Applied Meteorology and Climatology, 23(12), 1674–1687.