
Detecção e Visualização de Ondas de Calor
Pipeline INMET →
Preenchimento → Indicadores → Ondas de Calor |
sus_climate_compute_heatwaves() e
sus_climate_plot_heatwaves()
Dr. Max Anjos
Thauã Menezes
17 October, 2026
Source:vignettes/ondas_de_calor.Rmd
ondas_de_calor.RmdIntrodução
As ondas de calor estão entre os eventos climáticos extremos de maior relevância para a saúde pública, especialmente em um contexto de aquecimento global, urbanização acelerada e aumento da vulnerabilidade socioambiental. Esses eventos são caracterizados por períodos persistentes de temperaturas anormalmente elevadas em relação ao padrão climatológico de uma determinada localidade, podendo afetar diretamente o conforto térmico, a demanda por serviços de saúde, a mortalidade e a morbidade por causas sensíveis ao calor.
No Brasil, episódios recentes de calor extremo têm evidenciado a necessidade de ferramentas capazes de identificar, quantificar e visualizar ondas de calor de forma padronizada e reprodutível. Essa necessidade é ainda mais importante em estudos aplicados ao Sistema Único de Saúde (SUS), nos quais a integração entre dados meteorológicos, indicadores ambientais e desfechos em saúde permite investigar padrões de risco, subsidiar sistemas de alerta e apoiar estratégias de vigilância em saúde ambiental.
O pacote climasus4r oferece um pipeline integrado que
vai desde o download de dados meteorológicos horários do INMET até o
preenchimento de lacunas, cálculo de indicadores climáticos, detecção de
ondas de calor e visualização dos eventos. Neste tutorial, apresentamos
cada etapa desse processo com exemplos práticos, destacando não apenas a
execução das funções, mas também a interpretação climatológica,
epidemiológica e operacional 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 única e universalmente aceita para onda de calor. Em geral, uma onda de calor pode ser entendida como um período de calor anormal, intenso e persistente, no qual a temperatura observada ultrapassa um determinado limiar de referência por vários dias consecutivos. Esse limiar pode ser definido de forma absoluta, como uma temperatura fixa, ou de forma relativa, como um percentil elevado da distribuição histórica de temperatura de uma determinada região.
Essa distinção é importante porque o impacto do calor depende do contexto climático local. Uma temperatura considerada extrema em uma cidade de clima mais ameno pode ser relativamente comum em regiões tropicais ou semiáridas. Por esse motivo, muitos estudos utilizam limiares baseados em percentis, como o percentil 90 ou 95, permitindo que a definição de calor extremo seja adaptada à climatologia de cada localidade.
De modo geral, a maioria das definições de onda de calor combina dois componentes principais:
- 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.
- 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:
Onde:
- EHI_sig (índice de significância): , 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): , 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)
# )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).