Skip to contents

Introdução

Ondas de frio são eventos climáticos extremos frequentemente subestimados na agenda de saúde pública brasileira. Embora o Brasil seja conhecido por seu clima quente, o Sul e o Sudeste do país experimentam episódios periódicos de frio intenso associados à penetração de massas polares atlânticas, causando excesso de mortalidade cardiovascular e respiratória — em especial entre idosos, crianças e trabalhadores ao ar livre (Gasparrini et al., 2015; Huynen et al., 2001). Estudos globais estimam que o risco atribuível ao frio supera o do calor em muitas regiões, inclusive em zonas subtropicais (Gasparrini et al., 2015).

No Rio Grande do Sul, frentes frias polares podem reduzir a temperatura em 10–15 °C em menos de 24 horas durante o inverno austral (junho–agosto). Em Porto Alegre, episódios com temperaturas mínimas abaixo de 5 °C duram frequentemente 5 a 10 dias consecutivos, impondo carga adicional sobre o sistema respiratório e cardiovascular de populações vulneráveis. A ausência de sistemas de vigilância de ondas de frio comparáveis aos de ondas de calor contribui para que esse risco permaneça subdiagnosticado nas análises do SUS.

O climasus4r implementa sete metodologias internacionalmente reconhecidas para detecção de ondas de frio, seguindo a mesma estrutura de pipeline já disponível para ondas de calor. Este tutorial demonstra o pipeline completo desde o download de dados INMET até a visualização interativa dos resultados, utilizando a estação de Porto Alegre (A801) como caso de estudo.

Nota sobre reprodutibilidade: Todo o pipeline é determinístico — dado o mesmo período de dados INMET e os mesmos parâmetros, os resultados são idênticos entre execuções. Os blocos de código marcados com eval = FALSE precisam de conexão com a internet para a etapa de download (INMET) e podem demorar alguns minutos dependendo do período solicitado.

O que é uma onda de frio?

Assim como as ondas de calor, as ondas de frio são definidas por dois componentes:

  1. Limiar de temperatura — a temperatura (ou índice de conforto térmico) deve cair abaixo de determinado valor crítico, tipicamente definido como um percentil baixo da distribuição histórica (P10, P5) ou como um desvio negativo fixo em relação à média climatológica. Enquanto as ondas de calor usam a cauda superior (P90), as ondas de frio usam a cauda inferior (P10).
  2. Duração mínima — a condição extrema deve persistir por pelo menos N dias consecutivos (comumente 3 ou 5 dias), distinguindo eventos sustentados de quedas de temperatura isoladas.

A ausência de uma definição universal reflete a variabilidade regional do clima e dos limiares de tolerância fisiológica. O critério INMET para frio, por exemplo, usa um desvio absoluto de −5 °C sobre a temperatura mínima histórica (Tmin − 5 °C), em vez da temperatura máxima utilizada no critério de ondas de calor.

Por que comparar métodos? Em regiões subtropicais como o Rio Grande do Sul, o método INMET — calibrado para a realidade climática nacional usando temperatura mínima — tende a detectar eventos que percentis genéricos podem não capturar em anos atipicamente frios. O ECF (Excess Cold Factor, análogo ao EHF para frio) é o único método que considera o fator de aclimatação: a mesma temperatura mínima é fisiologicamente mais estressante quando ocorre após um período relativamente quente, pois o organismo não teve tempo de se adaptar ao frio. Comparar os sete métodos é uma boa prática de análise de sensibilidade.

Visão geral do 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 recebe o produto da anterior e adiciona informação. A função sus_climate_compute_coldwaves() espera dados horários com colunas padronizadas de temperatura e índices de conforto térmico — exatamente o que sus_climate_compute_indicators() produz.


Configuração do ambiente

# Instalar climasus4r (GitHub) se necessário
# install.packages("remotes")
# remotes::install_github("MaxAnjos/climasus4r")

library(climasus4r)
library(dplyr)

Dependências opcionais: As funções de visualização requerem ggplot2, ggsci e plotly. Para gráficos interativos, instale também htmlwidgets. A etapa de indicadores climáticos requer slider (janelas deslizantes) e jsonlite.

install.packages(c("ggplot2", "ggsci", "plotly", "htmlwidgets", "slider", "jsonlite"))

Etapa 1 — Aquisição de dados climáticos (INMET)

A rede de estações INMET

O Instituto Nacional de Meteorologia (INMET) opera a maior rede de estações meteorológicas automáticas do Brasil, com cobertura em todos os estados. Os dados são disponibilizados em formato CSV com resolução horária e incluem temperatura do ar (bulbo seco, máxima, mínima), umidade relativa, velocidade e direção do vento, pressão atmosférica e precipitação.

A função sus_climate_inmet() automatiza o download, o parsing e a padronização desses arquivos para um formato pronto para análise.

Parâmetros principais

# 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 Descrição
years inteiro ou vetor Anos a baixar (ex.: 2020:2023)
uf character Sigla do estado para filtrar estações (ex.: "RS", "SC")
station_code character Código(s) específico(s) de estação INMET (ex.: "A801")
use_cache lógico Se TRUE, reaproveita arquivos já baixados em cache_dir
parallel lógico Habilita download paralelo via furrr/future (requer múltiplos núcleos)
workers inteiro ou NULL Número de workers; NULL detecta automaticamente via parallelly

Exemplo: estação de Porto Alegre (RS)

Neste tutorial, utilizamos dados da estação automática de Porto Alegre (código INMET A801), no Rio Grande do Sul — estado com o maior registro histórico de ondas de frio do Brasil. Porto Alegre, com latitude de aproximadamente −30°S, está sujeita à penetração regular de massas polares atlânticas durante o inverno austral, tornando-a um laboratório natural para o estudo de eventos de frio 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)

A saída é um data.frame com resolução horária e colunas padronizadas pelo 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, ...

Origem dos dados: Os dados brutos são os arquivos CSV disponibilizados publicamente pelo INMET em https://portal.inmet.gov.br/dadoshistoricos. O climasus4r faz o parsing automático de cada arquivo anual, aplica controle de qualidade e padroniza os nomes de colunas. Nenhuma interpolação ou modificação de valores é realizada nesta etapa.


Etapa 2 — Preenchimento de lacunas (gap-filling)

O problema das lacunas em séries horárias

Estações automáticas do INMET frequentemente apresentam lacunas causadas por falhas de transmissão, manutenção de equipamentos ou eventos climáticos extremos. A presença de valores ausentes (NA) em colunas de temperatura pode inviabilizar o cálculo de índices de conforto térmico e comprometer as estimativas percentílicas utilizadas na detecção de ondas de frio.

A função sus_climate_fill_inmet() implementa um preenchimento inteligente baseado em modelos de regressão treinados com covariáveis meteorológicas correlacionadas (temperatura do ar, umidade relativa, velocidade do vento, hora do dia, sazonalidade). O preenchimento é realizado variável por variável e respeita um limiar máximo de lacunas (gap_percentage): se a proporção de valores ausentes em determinada série superar esse limiar, a estação é marcada como de baixa qualidade e nenhum preenchimento é aplicado.

Parâmetros principais

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"
)

Preenchimento do conjunto completo

Na prática, aplicamos o preenchimento a cada variável de temperatura e umidade relevante antes de calcular os indicadores de conforto 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))
  )

Boa prática: Sempre aplique sus_climate_fill_inmet() antes de sus_climate_compute_coldwaves(). A função de detecção emite um aviso (cli_warn) se encontrar NAs nas colunas de temperatura, mas não os preenche automaticamente — essa decisão cabe ao analista, pois diferentes estratégias de imputação podem influenciar os resultados.


Etapa 3 — Cálculo de indicadores climáticos

Por que ir além da temperatura do ar?

A temperatura do ar (bulbo seco) é a variável meteorológica mais disponível, mas não é a melhor proxy para o estresse térmico humano em condições de frio. O corpo humano responde ao ambiente frio resultante da combinação de temperatura, umidade, velocidade do vento (fator de resfriamento eólico) e radiação. Índices de conforto térmico integram esses fatores e permitem estimar a percepção fisiológica do frio de forma mais realista.

A função sus_climate_compute_indicators() calcula os principais índices utilizados nas metodologias de detecção de ondas de frio implementadas no climasus4r. Para ondas de frio, o interesse recai sobre os valores mínimos diários desses índices:

<div class="feature-icon">🌬️</div>
<h3>UTCI</h3>
<p><strong>Universal Thermal Climate Index.</strong> Modelo biometeorológico de referência da ISO 15743. Integra temperatura, umidade, vento e radiação em uma temperatura equivalente fisiológica (°C). Em frio extremo, UTCI abaixo de −13 °C indica estresse frio forte.</p>
<div class="feature-icon">❄️</div>
<h3>WBGT</h3>
<p><strong>Wet Bulb Globe Temperature.</strong> Índice operacional amplamente utilizado em saúde ocupacional. Em regimes frios, valores baixos de WBGT indicam risco de hipotermia e lesões por congelamento em trabalhadores ao ar livre.</p>
<div class="feature-icon">🧊</div>
<h3>HI</h3>
<p><strong>Heat Index (Índice de Calor).</strong> Embora concebido para calor, valores baixos do HI mínimo diário podem ser usados como indicador de conforto térmico precário em condições de frio e alta umidade.</p>
<div class="feature-icon">🌿</div>
<h3>PET</h3>
<p><strong>Physiological Equivalent Temperature.</strong> Temperatura de um ambiente de referência com as mesmas trocas de calor do corpo. Em valores negativos, indica desconforto fisiológico intenso por frio.</p>

Chamada da função

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)

Após esta etapa, o data.frame contém as colunas adicionais necessárias para a detecção de ondas de frio pelos métodos UTCI, WBGT e HI:

Coluna nova Índice Unidade
utci_c UTCI °C
wbgt_c WBGT °C
hi_c Heat Index °C
pet_c PET °C
utci_c_flag_extreme Horas com UTCI > 38 °C lógico
wbgt_c_flag_extreme Horas com WBGT > 32 °C lógico
hi_c_flag_extreme Horas com HI > 51 °C lógico

Faixas frias do UTCI: A norma ISO 15743 define categorias de estresse frio pelo UTCI: sem estresse térmico (≥ 9 °C), leve estresse frio (0–9 °C), estresse frio moderado (−13 a 0 °C), forte estresse frio (−27 a −13 °C) e estresse frio muito forte (< −27 °C). Na detecção de ondas de frio, o método UTCI no climasus4r utiliza o UTCImin diário — o menor valor horário de UTCI registrado naquele dia — comparado com o P10 histórico desse mesmo indicador.


Etapa 4 — Detecção de ondas de frio

A função sus_climate_compute_coldwaves()

Esta é a função central do módulo de detecção de frio do climasus4r. Ela recebe dados horários (produto de sus_climate_compute_indicators()), os agrega para escala diária, calcula limiares históricos percentílicos por estação do ano (usando uma janela deslizante de ±15 dias ao redor de cada dia do ano), aplica cada metodologia de detecção selecionada e retorna uma lista estruturada com três componentes.

Assinatura 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 o argumento method = "EHF": O identificador "EHF" é mantido por consistência com a API de ondas de calor, mas internamente a função aplica o algoritmo do Excess Cold Factor (ECF) — o análogo frio do EHF. O ECF foi proposto por Nairn & Fawcett (2015) e adaptado aqui para detectar eventos de frio extremo com base em temperatura média diária e fator de aclimatação.

Metodologias implementadas

A Tabela 1 apresenta as sete metodologias implementadas, incluindo a variável-base, o critério de limiar e a duração mínima padrão.

Tabela 1 — Metodologias de detecção de ondas de frio implementadas em sus_climate_compute_coldwaves()

Método Variável-base Critério de limiar Duração mínima Referência
WHO Tmin diária Tmin < P10(Tmin) 3 dias WMO & WHO (2015)
WMO Tmin e Tmax diárias Tmin < P10(Tmin) E Tmax < P10(Tmax) 5 dias Perkins & Alexander (2013)
INMET Tmin diária Tmin < média histórica − 5 °C 5 dias INMET (2009)
ECF Tmean diária ECF > 0 (fórmula composta; ver abaixo) 3 dias Nairn & Fawcett (2015)*
UTCI UTCImin diário UTCImin < P10(UTCImin) 3 dias ISO 15743
WBGT WBGTmin diário WBGTmin < P10(WBGTmin) 3 dias Liljegren et al. (2008)
HI HImin diário HImin < P10(HImin) 3 dias Steadman (1979)

*Adaptação para frio: ECF (Excess Cold Factor) em vez de EHF (Excess Heat Factor).

Suavização sazonal dos percentis: Para todos os métodos baseados em percentil, o climasus4r utiliza uma janela deslizante de ±15 dias em torno de cada dia do ano (calculada sobre o período de referência), e não um percentil fixo calculado sobre toda a série. Essa abordagem, recomendada por Fischer & Schär (2010), elimina o viés sazonal e garante que o mesmo nível de extremidade relativa seja detectado em qualquer época do ano. Para ondas de frio, o percentil é calculado na cauda inferior da distribuição (P10), em oposição ao P90 usado para ondas de calor.

Fundamentos do Excess Cold Factor (ECF)

O ECF é o análogo frio do EHF (Nairn & Fawcett, 2015). Ele combina dois componentes que capturam, respectivamente, a magnitude absoluta do frio e o fator de aclimatação da população:

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

Onde:

  • ECI_sig (índice de significância do frio): P5(T‾mean)−T‾3P_5(\bar{T}_{mean}) - \bar{T}_3, mede o quanto a temperatura média dos últimos 3 dias está abaixo do percentil 5 climatológico da temperatura média. Valores positivos indicam frio fisiologicamente relevante.
  • ECI_acc (índice de aclimatação): T‾30−T‾3\bar{T}_{30} - \bar{T}_3, mede o quanto a temperatura média dos últimos 3 dias está abaixo da média dos 30 dias anteriores. Positivo quando o período recente é mais frio que o mês anterior — ou seja, o organismo estava aclimatado ao calor e foi subitamente exposto ao frio, amplificando o estresse fisiológico.

O multiplicador max⁡(1,ECIacc)\max(1, \text{ECI}_{acc}) garante que eventos de frio que ocorrem após período relativamente quente recebam maior peso — exatamente o inverso da lógica do EHF, onde o aquecimento súbito amplifica o risco de calor.

Dias com ECF > 0 são classificados como dias de onda de frio. A intensidade do evento é classificada em três categorias com base no percentil 85 (ECF85) de todos os valores positivos de ECF observados na estação:

  • Baixa Intensidade (LICW): 0 < ECF_peak < ECF85
  • Severa (SCW): ECF85 ≤ ECF_peak < 3 × ECF85
  • Extrema (ECW): ECF_peak ≥ 3 × ECF85

Método INMET: calibração para o frio no Brasil

O método INMET para frio define onda de frio quando a temperatura mínima diária cai abaixo da média climatológica da temperatura mínima por pelo menos 5 °C por 5 ou mais dias consecutivos (INMET, 2009). Diferentemente do critério de ondas de calor (que usa a temperatura máxima), o critério de frio usa a temperatura mínima — a variável mais sensível à penetração de massas polares.

A média climatológica da Tmin é calculada sobre o período de referência definido pelo usuário, utilizando a mesma janela deslizante de ±15 dias usada nos percentis. Esse critério é particularmente adequado para o Sul do Brasil, onde os valores absolutos de Tmin já são baixos e a vulnerabilidade à mortalidade por frio está mais associada ao desvio em relação à norma local do que ao valor absoluto.

Executando a detecção

Exemplo 1: métodos baseados em temperatura do ar

# 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
)

Exemplo 2: todos os métodos (incluindo índices de conforto)

# 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
)

Exemplo 3: critério 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álise de sensibilidade: Recomenda-se executar a detecção com diferentes combinações de percentil (P5, P10, P15) e duração mínima (3, 5, 7 dias) e comparar o número de eventos detectados. Isso permite avaliar a robustez dos resultados epidemiológicos em relação às escolhas metodológicas.

Baseline curto neste tutorial: Este tutorial usa apenas 4 anos de dados (2020–2023) para agilizar o download. O climasus4r emite um aviso quando o baseline tem menos de 20 anos, o que é esperado aqui. Para pesquisa real, recomenda-se usar pelo menos 1981–2010 ou 1991–2020 como período de referência climatológica.

Estrutura do output

A função retorna uma lista nomeada com três componentes — mesma estrutura do output de sus_climate_compute_heatwaves(), mas com nomenclatura adaptada para frio:

# Inspecionar o output
names(cw_all)
#> [1] "events"  "daily"   "summary"

$events — tabela de eventos

Um data.frame com uma linha por evento de onda de frio detectado. Cada linha representa um episódio contínuo de dias com a condição de onda de frio ativa para um determinado método e estação.

# Primeiros eventos detectados
head(cw_all$events)
Coluna Tipo Descrição
event_id character Identificador único: <estação>_<método>_<N>
station_code character Código INMET da estação
method character Método de detecção (WHO, WMO, etc.)
start_date Date Data de início do evento
end_date Date Data de fim do evento
duration_days integer Duração em dias consecutivos
temp_mean double Temperatura média do período (variável do método)
temp_peak double Temperatura mais fria do período (mínimo)
anomaly_mean double Anomalia média (limiar − temperatura; positivo = mais frio que o limiar)
anomaly_cumulative double Anomalia acumulada ao longo do evento
severity_index double Índice de severidade: duração × anomalia média
ecf_peak double Pico do ECF (apenas método EHF/ECF; NA para outros)
ecf_mean double Média do ECF durante o evento (apenas EHF/ECF)
intensity_class character Classificação: LICW, SCW, ECW (apenas EHF/ECF)
region character Região geográfica da estação
federal_unit character UF da estação

Diferenças importantes em relação ao output de ondas de calor:

Campo Ondas de Calor Ondas de Frio
temp_peak Temperatura mais quente do evento Temperatura mais fria do evento
anomaly_mean temp − limiar (positivo = mais quente) limiar − temp (positivo = mais frio)
Flags diários hw_who, hw_any, … cw_who, cw_any, …
ECF-específico ehf_peak, ehf_mean ecf_peak, ecf_mean
Resumo anual total_days_hw total_days_cw
Classes de intensidade 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 — série diária com flags

O data.frame diário contém uma linha por estação por dia, com as variáveis agregadas e colunas lógicas (TRUE/FALSE) indicando se aquele dia pertence a uma onda de frio segundo cada método:

# Inspecionar colunas de flags
cw_all$daily |>
  select(station_code, date_day, tmin, tmean, starts_with("cw_")) |>
  head(10)

A coluna cw_any é TRUE se qualquer método detectou onda de frio naquele dia — útil para análises de exposição sem comprometimento com um único critério.

# 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 — resumo anual

O resumo anual agrega as estatísticas por estação, método e ano, sendo o ponto de entrada natural para análises de tendência 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))
Coluna Descrição
year Ano
station_code Código da estação
method Método de detecção
n_events Número de eventos no ano
total_days_cw Total de dias de onda de frio no ano
mean_duration Duração média dos eventos (dias)
max_duration Duração do evento mais longo (dias)
mean_intensity Temperatura média nos eventos
max_intensity Temperatura de pico (mais fria) nos eventos
mean_anomaly Anomalia média nos eventos
severity_total Soma dos índices de severidade dos eventos no ano

Etapa 5 — Visualização de ondas de frio

A função sus_climate_plot_coldwaves()

A visualização transforma o output estruturado de sus_climate_compute_coldwaves() em gráficos interpretativos com paleta de cores frias (tons de azul e violeta). A função oferece quatro tipos de visualização, cada um respondendo a uma pergunta analítica diferente:

<div class="feature-icon">📅</div>
<h3>timeline</h3>
<p>Diagrama de Gantt mostrando a posição temporal, duração e intensidade de cada evento. Ideal para identificar episódios de frio prolongados no inverno austral e comparar métodos.</p>
<div class="feature-icon">🗓️</div>
<h3>calendar</h3>
<p>Mapa de calor calendário que exibe a ocorrência diária de ondas de frio ao longo dos meses. Revela a concentração sazonal (inverno austral) e padrões interanuais associados a La Niña.</p>
<div class="feature-icon">❄️</div>
<h3>intensity</h3>
<p>Dispersão duração × temperatura mínima de pico, com eixo Y invertido (mais frio = mais alto). Distingue eventos longos de eventos com temperaturas extremamente baixas.</p>
<div class="feature-icon">📈</div>
<h3>trend</h3>
<p>Barras agrupadas do número de eventos por ano e método. Permite identificar variabilidade interanual e possíveis tendências na frequência de ondas de frio.</p>

Assinatura 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 Opções Efeito
type "timeline", "calendar", "intensity", "trend" Tipo de gráfico
interactive TRUE (plotly), FALSE (ggplot2) Interatividade
color_palette qualquer paleta do pacote ggsci Esquema de cores (aplicado sobre paleta base de azuis)
lang "pt", "en", "es" Idioma dos rótulos
save_plot caminho .html ou .png Salvar o gráfico em disco

Plot 1: Linha do tempo (timeline)

O gráfico de linha do tempo apresenta cada evento como um segmento horizontal (estilo Gantt), com espessura proporcional à duração e cor indicando a classe de intensidade ECF (para o método EHF/ECF; para outros métodos, eventos são exibidos em 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)

Interpretação: Segmentos mais longos indicam eventos mais duradouros; a espessura reforça visualmente a duração. Observe a concentração de eventos em junho–agosto (inverno austral). O método WMO (duplo limiar: Tmin e Tmax < P10) tende a gerar menos eventos e de maior duração que o WHO (apenas Tmin), pois exige que tanto o dia quanto a noite sejam excepcionalmente frios.

Plot 2: Calendário (calendar)

O calendário exibe cada dia do ano em células coloridas — azul para dias de onda de frio, cinza para dias normais. É o gráfico mais intuitivo para comunicar a sazonalidade dos eventos ao público não 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"
)

Interpretação: Observe a concentração de dias de onda de frio em junho, julho e agosto no Sul do Brasil. Anos com eventos La Niña (que tendem a intensificar frentes frias no RS) apresentam calendários com mais blocos azuis consecutivos. Esses períodos merecem atenção especial na análise de mortalidade respiratória e cardiovascular no SUS.

Plot 3: Intensidade vs. duração (intensity)

Este gráfico de dispersão posiciona cada evento no plano cartesiano duração × temperatura mínima de pico. O eixo Y é invertido (scale_y_reverse()), de modo que temperaturas mais baixas (mais frias, mais extremas) aparecem na parte superior do gráfico — convenção que torna intuitiva a interpretação: quanto mais alto e à direita, maior o risco 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"
)

Interpretação: Eventos no quadrante superior direito (longa duração + temperatura muito baixa) são os mais perigosos do ponto de vista de saúde pública. O ECF captura a nuance de aclimatação: um evento com Tmin de 5 °C após um período de inverno consolidado é menos estressante do que a mesma temperatura ocorrendo imediatamente após dias quentes — exatamente o que o componente ECI_acc mede.

Plot 4: Tendência anual (trend)

O gráfico de tendência mostra o número de eventos detectados por ano para cada método, permitindo avaliar a variabilidade interanual e possíveis tendências na frequência de ondas de frio ao longo do período analisado.

# 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"
)

Interpretação: A variabilidade interanual de ondas de frio é grande e fortemente influenciada pelo ENSO (El Niño–Oscilação Sul): La Niña tende a aumentar a frequência e intensidade de frentes frias no Sul do Brasil. Compare os padrões entre métodos: o método INMET tende a ser mais restritivo (exige desvio de −5 °C sobre a Tmin histórica), enquanto os métodos percentílicos capturam a relatividade do evento em relação ao histórico local.

Salvando 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álise avançada dos resultados

Integrando eventos ao calendário epidemiológico

O componente $daily com a coluna cw_any pode ser diretamente cruzado com dados de mortalidade e morbidade do SUS para calcular excesso de óbitos e internações durante ondas de frio:

# 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álise externa

# 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álise de concordância 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))

A análise de concordância responde a uma pergunta central da epidemiologia ambiental: em quantos dos dias classificados como onda de frio há consenso entre os métodos? Alta concordância aumenta a confiança nos resultados; baixa concordância sugere que o impacto em saúde pode variar significativamente dependendo do critério adotado.


Referências

Mortalidade por frio — epidemiologia 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 e Sul

  • 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.

Conceitos gerais e framework de percentis

  • 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 e WMO (adaptados para frio)

  • WMO & WHO (2015). Heatwaves and Health: Guidance on Warning-System Development. Organização Meteorológica Mundial, Genebra.
  • WMO (2021). Guidelines on the Definition and Monitoring of Extreme Weather and Climate Events. Organização 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) — regime frio

  • 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. Organização Internacional de Normalização.

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.

Informações da sessão


climasus4r · Análise integrada saúde–clima–ambiente no Brasil

Encontrou um problema ou tem sugestões para este tutorial?

🐛 Reportar no GitHub