Skip to contents

Introdução

Ondas de calor figuram entre os fenômenos climáticos extremos de maior impacto sobre a saúde pública. No Brasil, eventos como as ondas de calor de 2023–2024 no Centro-Sul causaram excesso de mortalidade cardiovascular, respiratória e neurológica, especialmente em populações vulneráveis — idosos, trabalhadores ao ar livre e residentes em áreas urbanas densas com pouca cobertura arbórea (Fiocruz, 2025; Observatório do Clima, 2024). A detecção rigorosa e reprodutível desses eventos é, portanto, pré-requisito para qualquer estudo de epidemiologia ambiental aplicado ao Sistema Único de Saúde (SUS).

O climasus4r oferece um pipeline integrado que vai do download de dados meteorológicos brutos do INMET até a detecção e visualização de ondas de calor, utilizando sete metodologias internacionalmente reconhecidas. Este tutorial demonstra cada etapa desse pipeline com exemplos executáveis e interpreta o significado clínico e epidemiológico dos resultados.

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 calor?

Não existe uma definição universal de onda de calor. A literatura científica apresenta dezenas de critérios, que variam conforme o contexto geográfico, a variável climática priorizada e o desfecho em saúde investigado (Perkins, 2015). Em geral, toda definição envolve dois componentes:

  1. Limiar de temperatura — a temperatura (ou índice de conforto térmico) deve superar determinado valor crítico, tipicamente definido como um percentil alto da distribuição histórica (P90, P95) ou como um desvio fixo em relação à média climatológica.
  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 picos isolados.

A ausência de consenso não é uma limitação operacional: o climasus4r implementa as sete definições mais utilizadas na literatura (Tabela 1), permitindo análises de sensibilidade e comparações intermetodológicas.

Por que comparar métodos? Em regiões tropicais e subtropicais como o Brasil, o método INMET — calibrado para a realidade climática nacional — tende a detectar eventos que métodos percentílicos genéricos podem subestimar. Por outro lado, índices de conforto térmico como UTCI e WBGT capturam a percepção fisiológica de calor de forma mais completa do que a temperatura do ar isolada. Comparar resultados entre 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_heatwaves() 5. sus_climate_plot_heatwaves()

Cada etapa recebe o produto da anterior e adiciona informação. A função sus_climate_compute_heatwaves() 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        = 2010:2023,   # Vetor de anos
  uf           = "RN",        # 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     = TRUE,        # Download paralelo
  workers      = 4,           # Número de workers
  lang         = "pt",
  verbose      = TRUE
)
Parâmetro Tipo Descrição
years inteiro ou vetor Anos a baixar (ex.: 2010:2023)
uf character Sigla do estado para filtrar estações (ex.: "RN", "SP")
station_code character Código(s) específico(s) de estação INMET (ex.: "A304")
use_cache lógico Se TRUE, reaproveita arquivos já baixados em cache_dir
parallel lógico Habilita download paralelo via furrr/future
workers inteiro Número de workers para execução paralela

Exemplo: estação de Natal (RN)

Neste tutorial, utilizamos dados da estação automática de Natal (código INMET A304), no Rio Grande do Norte — estado do Nordeste brasileiro com clima semiárido e histórico de ondas de calor intensas.

# Download de dados horários (2010–2023)
# A primeira execução pode levar alguns minutos; execuções subsequentes usam cache.
df_inmet <- sus_climate_inmet(
  years        = 2010:2023,
  station_code = "A304",   # Natal - RN
  use_cache    = TRUE,
  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: ~122,640  (14 anos × 365 dias × 24 horas)
#>  Columns: ~20
#> 
#>  $ date               <POSIXct>  2010-01-01 00:00:00, 2010-01-01 01:00:00 ...
#>  $ station_code       <chr>      'A304', 'A304', ...
#>  $ station_name       <chr>      'NATAL', 'NATAL', ...
#>  $ federal_unit       <chr>      'RN', 'RN', ...
#>  $ region             <chr>      'Nordeste', 'Nordeste', ...
#>  $ latitude           <dbl>      -5.84, -5.84, ...
#>  $ longitude          <dbl>      -35.21, -35.21, ...
#>  $ tair_dry_bulb_c    <dbl>      28.4, 27.9, ...
#>  $ tair_max_c         <dbl>      29.1, 28.6, ...
#>  $ tair_min_c         <dbl>      27.8, 27.3, ...
#>  $ rh_pct             <dbl>      82.0, 84.0, ...
#>  $ wind_speed_ms      <dbl>      3.2, 2.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 calor.

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_heatwaves(). 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. O corpo humano responde ao ambiente térmico resultante da combinação de temperatura, umidade, radiação solar e velocidade do vento. Índices de conforto térmico integram esses quatro fatores e permitem estimar a percepção fisiológica de calor de forma mais realista.

A função sus_climate_compute_indicators() calcula os principais índices utilizados nas metodologias de detecção de ondas de calor implementadas no climasus4r:

<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).</p>
<div class="feature-icon">💧</div>
<h3>WBGT</h3>
<p><strong>Wet Bulb Globe Temperature.</strong> Índice operacional amplamente utilizado em saúde ocupacional e esportes. Combina temperatura úmida, temperatura do globo negro e temperatura do ar seco.</p>
<div class="feature-icon">🥵</div>
<h3>HI</h3>
<p><strong>Heat Index (Índice de Calor).</strong> Temperatura aparente calculada a partir do bulbo seco e da umidade relativa. Indica como o calor é percebido pela população em geral.</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. Frequentemente utilizado em estudos de conforto urbano.</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
  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 calor 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

Etapa 4 — Detecção de ondas de calor

A função sus_climate_compute_heatwaves()

Esta é a função central do módulo climático 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

hw_result <- sus_climate_compute_heatwaves(
  data           = df_indicators,   # Output de sus_climate_compute_indicators()
  method         = c("WHO", "WMO", "INMET", "EHF", "UTCI", "WBGT", "HI"),
  baseline_start = "2010-01-01",    # Início do período de referência
  baseline_end   = "2020-12-31",    # Fim do período de referência
  percentile     = 90,              # Percentil para limiares (P90 por padrão)
  min_duration   = NULL,            # NULL = usar defaults por método
  lang           = "pt",
  verbose        = TRUE
)

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 calor implementadas em sus_climate_compute_heatwaves()

Método Variável-base Critério de limiar Duração mínima Referência
WHO Tmax diária Tmax > P90(Tmax) 3 dias WMO & WHO (2015)
WMO Tmax e Tmin diárias Tmax > P90(Tmax) E Tmin > P90(Tmin) 5 dias Perkins & Alexander (2013)
INMET Tmax diária Tmax > média histórica + 5°C 5 dias INMET (2009)
EHF Tmean diária EHF > 0 (fórmula composta; ver abaixo) 3 dias Nairn & Fawcett (2015)
UTCI UTCImax diário UTCImax > P90(UTCImax) 3 dias Broede et al. (2012)
WBGT WBGTmax diário WBGTmax > P90(WBGTmax) 3 dias Liljegren et al. (2008)
HI HImax diário HImax > P90(HImax) 3 dias Steadman (1979)

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.

Fundamentos do Excess Heat Factor (EHF)

O EHF (Nairn & Fawcett, 2015) é o único método que não utiliza percentis diretos da variável-base. Ele combina dois componentes:

EHF=EHIsig×max(1,EHIacc)\text{EHF} = \text{EHI}_{sig} \times \max(1, \text{EHI}_{acc})

Onde:

  • EHI_sig (índice de significância): T3T95\bar{T}_3 - T_{95}, mede o quanto a temperatura média dos últimos 3 dias supera o percentil 95 climatológico da temperatura média. Captura a magnitude absoluta do calor.
  • EHI_acc (índice de aclimatação): T3T30\bar{T}_3 - \bar{T}_{30}, mede o quanto a temperatura média dos últimos 3 dias supera a média dos 30 dias anteriores. Captura a velocidade de aquecimento e a capacidade de aclimatação da população.

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

  • Baixa Intensidade (LIHW): 0 < EHF_peak < EHF85
  • Severa (SHW): EHF85 ≤ EHF_peak < 3 × EHF85
  • Extrema (EHW): EHF_peak ≥ 3 × EHF85

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

O método INMET define onda de calor quando a temperatura máxima diária supera a média climatológica da temperatura máxima por pelo menos 5°C por 5 ou mais dias consecutivos (INMET, 2009). A média climatológica é calculada sobre o período de referência definido pelo usuário (recomenda-se 1981–2010 ou 1991–2020, conforme disponibilidade de dados).

Este critério é particularmente adequado para o contexto tropical e subtropical brasileiro, onde os valores absolutos de temperatura já são elevados e o impacto sobre a saúde está mais associado 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)
hw_temp <- sus_climate_compute_heatwaves(
  data           = df_indicators,
  method         = c("WHO", "WMO", "INMET", "EHF"),
  baseline_start = "2010-01-01",
  baseline_end   = "2020-12-31",
  percentile     = 90,
  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
hw_all <- sus_climate_compute_heatwaves(
  data           = df_indicators,
  method         = "all",          # Equivale a c("WHO","WMO","INMET","EHF","UTCI","WBGT","HI")
  baseline_start = "2010-01-01",
  baseline_end   = "2020-12-31",
  percentile     = 90,
  lang           = "pt",
  verbose        = TRUE
)

Exemplo 3: customizando o percentil e a duração mínima

# Critério mais conservador: P95 e mínimo de 5 dias para todos os métodos
hw_strict <- sus_climate_compute_heatwaves(
  data           = df_indicators,
  method         = c("WHO", "INMET"),
  baseline_start = "2010-01-01",
  baseline_end   = "2020-12-31",
  percentile     = 95,       # Limiar mais alto → 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 (P85, P90, P95) 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.

Estrutura do output

A função retorna uma lista nomeada com três componentes:

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

$events — tabela de eventos

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

# Primeiros eventos detectados
head(hw_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 máxima do período
anomaly_mean double Anomalia média (temperatura - limiar)
anomaly_cumulative double Anomalia acumulada ao longo do evento
severity_index double Índice de severidade: duração × anomalia média
ehf_peak double Pico do EHF (apenas método EHF; NA para outros)
ehf_mean double Média do EHF durante o evento (apenas EHF)
intensity_class character Classificação: Low, Severe, Extreme (apenas EHF)
region character Região geográfica da estação
federal_unit character UF da estação
# Filtrar os 10 eventos mais severos pelo índice de severidade
hw_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
hw_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 calor segundo cada método:

# Inspecionar colunas de flags
hw_all$daily |>
  select(station_code, date_day, tmax, tmean, starts_with("hw_")) |>
  head(10)

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

# Dias com onda de calor ativa por pelo menos um método
hw_all$daily |>
  filter(hw_any == TRUE) |>
  select(date_day, tmax, tmean, hw_who, hw_inmet, hw_ehf, hw_utci) |>
  head(20)
# Concordância entre métodos: proporção de dias classificados por cada um
hw_all$daily |>
  summarise(
    pct_who   = mean(hw_who,   na.rm = TRUE) * 100,
    pct_wmo   = mean(hw_wmo,   na.rm = TRUE) * 100,
    pct_inmet = mean(hw_inmet, na.rm = TRUE) * 100,
    pct_ehf   = mean(hw_ehf,   na.rm = TRUE) * 100,
    pct_utci  = mean(hw_utci,  na.rm = TRUE) * 100,
    pct_wbgt  = mean(hw_wbgt,  na.rm = TRUE) * 100,
    pct_hi    = mean(hw_hi,    na.rm = TRUE) * 100,
    pct_any   = mean(hw_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
hw_all$summary |>
  filter(method == "INMET") |>
  select(year, station_code, n_events, total_days_hw,
         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_hw Total de dias de onda de calor 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 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 calor

A função sus_climate_plot_heatwaves()

A visualização transforma o output estruturado de sus_climate_compute_heatwaves() em gráficos interpretativos. 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 comparar eventos entre métodos e estações.</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 calor ao longo dos meses. Revela padrões sazonais e distribuição intra-anual.</p>
<div class="feature-icon">⚡</div>
<h3>intensity</h3>
<p>Dispersão duração × temperatura de pico, com ponto colorido por classe de intensidade. Distingue eventos longos de eventos quentes.</p>
<div class="feature-icon">📈</div>
<h3>trend</h3>
<p>Barras agrupadas do número de eventos por ano e método. Permite identificar tendências de longo prazo na frequência de ondas de calor.</p>

Assinatura completa

p <- sus_climate_plot_heatwaves(
  hw_result     = hw_all,          # Output de sus_climate_compute_heatwaves()
  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
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 (relevante para EHF; para outros métodos, todos os eventos são classificados como “desconhecido” na legenda de intensidade).

# Linha do tempo de todos os eventos — todos os métodos
sus_climate_plot_heatwaves(
  hw_result   = hw_all,
  type        = "timeline",
  interactive = TRUE,
  lang        = "pt"
)
# Filtrar apenas eventos pelo método INMET
sus_climate_plot_heatwaves(
  hw_result   = hw_all,
  type        = "timeline",
  method      = "INMET",
  interactive = TRUE,
  lang        = "pt"
)
# Versão estática para publicação
p_timeline <- sus_climate_plot_heatwaves(
  hw_result     = hw_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_calor.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 que o método WMO (duplo limiar: Tmax E Tmin) tende a gerar menos eventos e de maior duração que o WHO (apenas Tmax), pois exige que tanto o dia quanto a noite sejam excepcionalmente quentes.

Plot 2: Calendário (calendar)

O calendário exibe cada dia do ano em células coloridas — vermelho para dias de onda de calor, 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_heatwaves(
  hw_result   = hw_all,
  type        = "calendar",
  method      = "WHO",
  year        = 2023,
  interactive = TRUE,
  lang        = "pt"
)
# Calendário com hw_any (qualquer método) — todos os anos
sus_climate_plot_heatwaves(
  hw_result   = hw_all,
  type        = "calendar",
  method      = NULL,          # NULL → usa hw_any (qualquer método)
  interactive = FALSE,
  lang        = "pt"
)

Interpretação: Observe a concentração de dias de onda de calor nos meses de verão austral (dezembro–março) no Nordeste. Anos com múltiplos blocos vermelhos consecutivos merecem atenção especial: nesses períodos, o excesso de mortalidade no SUS tende a ser maior (Fiocruz, 2025).

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

Este gráfico de dispersão posiciona cada evento no plano cartesiano duração × temperatura de pico. A coloração por classe de intensidade EHF (quando disponível) permite identificar eventos que combinam longa duração e alta temperatura — os de maior risco epidemiológico.

# Intensidade EHF (com classificação Low / Severe / Extreme)
sus_climate_plot_heatwaves(
  hw_result   = hw_all,
  type        = "intensity",
  method      = "EHF",
  interactive = TRUE,
  lang        = "pt"
)
# Todos os métodos juntos (sem classificação de intensidade EHF)
sus_climate_plot_heatwaves(
  hw_result   = hw_all,
  type        = "intensity",
  method      = NULL,
  interactive = FALSE,
  lang        = "pt"
)

Interpretação: Eventos no quadrante superior direito (longa duração + alta temperatura) são os mais perigosos do ponto de vista de saúde pública. Eventos no quadrante inferior direito (longa duração + temperatura moderada) podem ser igualmente perigosos para populações sem aclimatação. O EHF captura essa nuance através do componente EHI_acc (aclimatação), penalizando eventos que ocorrem após período anormalmente frio.

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 identificar se a frequência de ondas de calor está aumentando ao longo do período analisado — uma das principais previsões dos cenários de mudança climática para o Brasil.

# Tendência anual — todos os métodos
sus_climate_plot_heatwaves(
  hw_result   = hw_all,
  type        = "trend",
  interactive = TRUE,
  lang        = "pt"
)
# Tendência apenas para WHO e INMET (comparação de sensibilidade)
sus_climate_plot_heatwaves(
  hw_result   = hw_all,
  type        = "trend",
  method      = c("WHO", "INMET"),
  interactive = FALSE,
  lang        = "pt",
  save_plot   = "tendencia_ondas_calor.png"
)

Interpretação: Se a tendência de frequência for crescente, isso é consistente com o aquecimento regional. Compare os padrões entre métodos: o método INMET tende a ser mais restritivo em regiões já quentes (pois exige +5°C sobre a média histórica), enquanto os métodos percentílicos capturam aumentos relativos mesmo em regiões onde as temperaturas absolutas são elevadas durante todo o ano.

Salvando gráficos

# Gráfico interativo → arquivo HTML autossuficiente
sus_climate_plot_heatwaves(
  hw_result   = hw_all,
  type        = "timeline",
  interactive = TRUE,
  lang        = "pt",
  save_plot   = "ondas_calor_timeline.html"
)

# Gráfico estático → PNG de alta resolução (300 dpi)
sus_climate_plot_heatwaves(
  hw_result   = hw_all,
  type        = "trend",
  interactive = FALSE,
  lang        = "pt",
  save_plot   = "ondas_calor_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 hw_any pode ser diretamente cruzado com dados de mortalidade e morbidade do SUS para calcular excesso de óbitos e internações durante ondas de calor:

# 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 cardiovascular
# df_sim_diario <- sus_data_aggregate(df_sim, by = "day") |>
#   filter(cid_grupo == "I" | cid_grupo == "J")  # Cardiovascular + Respiratório

# 2. Adicionar flag de onda de calor
# df_analise <- df_sim_diario |>
#   left_join(
#     hw_all$daily |> select(date_day, hw_any, hw_inmet, tmax),
#     by = c("date" = "date_day")
#   )

# 3. Comparar mortalidade em dias com/sem onda de calor
# df_analise |>
#   group_by(hw_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(
  hw_all$events,
  file      = "eventos_ondas_calor_A304_2010_2023.csv",
  row.names = FALSE,
  fileEncoding = "UTF-8"
)

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

Análise de concordância entre métodos

# Proporção de dias classificados como onda de calor por N métodos simultaneamente
hw_all$daily |>
  mutate(
    n_methods = rowSums(
      across(c(hw_who, hw_wmo, hw_inmet, hw_ehf, hw_utci, hw_wbgt, hw_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 calor 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

Conceitos gerais e framework de percentis

  • Perkins, S.E. (2015). A review on the scientific understanding of heatwaves — their measurement, driving mechanisms, and changes at the global scale. Atmospheric Research, 164–165, 242–267. https://doi.org/10.1016/j.atmosres.2015.05.009
  • 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

  • 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.
  • MCTI/Gov.br (2025). Relatórios de ondas de calor no Brasil (online).

EHF (Excess Heat 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)

  • 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

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.
  • ISO 7243:2017. Ergonomics of the thermal environment — Assessment of heat stress using the WBGT index. Organização Internacional de Normalização.

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.

Contexto SUS e saúde pública brasileira

  • Fiocruz (2025). Excess cardiovascular mortality associated with extreme heatwaves in Southeast Brazil, 2014–2023. Cadernos de Saúde Pública.
  • Observatório do Clima (2024). Mortalidade excessiva durante ondas de calor em áreas urbanas brasileiras (2000–2018).

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