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
09 May, 2026
Source:vignettes/ondas_de_calor.Rmd
ondas_de_calor.RmdIntroduçã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:
- 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 |
$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).