Skip to contents

Introducció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:

  1. 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).
  2. 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:

ECF=ECIsig×max⁡(1,ECIacc)\text{ECF} = \text{ECI}_{sig} \times \max(1, \text{ECI}_{acc})

Donde:

  • ECI_sig (índice de significancia del frío): P5(T‾mean)−T‾3P_5(\bar{T}_{mean}) - \bar{T}_3, 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): T‾30−T‾3\bar{T}_{30} - \bar{T}_3, 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 max⁡(1,ECIacc)\max(1, \text{ECI}_{acc}) 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)
#   )

Exportando eventos para análisis externo

# Exportar tabela de eventos para CSV
write.csv(
  cw_all$events,
  file         = "eventos_ondas_frio_A801_2020_2023.csv",
  row.names    = FALSE,
  fileEncoding = "UTF-8"
)

# Exportar resumo anual
write.csv(
  cw_all$summary,
  file         = "resumo_anual_ondas_frio_A801.csv",
  row.names    = FALSE,
  fileEncoding = "UTF-8"
)

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.

Información de la sesión


climasus4r · Análisis integrado salud–clima–ambiente en Brasil

¿Encontró un problema o tiene sugerencias para este tutorial?

🐛 Reportar en GitHub