Sazonalidade por Semana Epidemiológica — Covid-19, Influenza e VSR
Autor
Unidade de Inteligencia e Vigilancia em Saude (UIVS) - SES/SP
Data de Publicação
4 de dezembro de 2025
1 Objetivo e racional
Este relatório investiga padrões sazonais semanais para Covid-19, Influenza e Vírus Sincicial Respiratório (VSR) ao longo dos anos, usando:
- Incidência semanal por 100 mil hab.
- Métricas sazonais (semana do pico, amplitude, duração da temporada, centro de gravidade temporal).
- Estatística circular para comparar o timing dos picos entre diagnósticos.
- Modelagem com GAM cíclico (captura sazonalidade flexível por semana).
- Correlação e defasagem entre séries (quem antecipa quem).
- Visualizações: heatmap semana×ano, subseries por ano, curvas suavizadas e polar.
2 Construção da incidência semanal
Abaixo calculamos a incidência semanal agregada (somando casos e populações municipais por ano) e forçamos a presença de todas as semanas (1–53) por diagnóstico×ano para evitar “quebras” nas linhas.
Nota de interpretação: usar a população total anual (soma das populações municipais únicas) evita dupla contagem e padroniza o denominador para comparar semanas dentro do mesmo ano.
3 Análises descritivas
3.1 1) Subseries (linhas por ano)
Leitura: picos recorrentes na mesma janela de semanas indicam sazonalidade estável.
Os perfis por ano mostram: Entre 2023–2025, os perfis semanais indicam sazonalidade estável para Influenza (picos SE16–21; maior amplitude em 2025) e VSR (picos SE13–18; amplitude crescente). A Covid-19 mantém pico precoce consistente (SE8–9), porém com queda acentuada de magnitude até 2025; só 2023 teve elevação tardia (SE40–42). Em suma, estabilidade temporal para Influenza/VSR, variabilidade de magnitude para Covid-19.
3.2 2) Heatmap semana × ano
Leitura: faixas verticais mais intensas indicam períodos de maior risco por ano.
Os heatmaps de 2023–2025 mostram “janelas quentes” claras: Influenza concentra-se no miolo do ano (SE15–26), com pico mais intenso em 2025 (SE21, 2,25/100 mil); o VSR antecipa essa janela (SE12–18), com padrão altamente consistente e intensidade crescente até 2025 (SE18, 1,49/100 mil). Já a Covid-19 concentra-se no início do ano (SE1–10), apresenta manchas menos regulares, um aumento tardio em 2023 (SE40–42) e queda marcante de magnitude em 2025 (pico de 0,68/100 mil).
3.3 3) Polar (visão circular do ano)
Filtros interativos:
Use os filtros acima para escolher quais diagnósticos e anos deseja visualizar simultaneamente.
Leitura: o ângulo (semana) do maior raio indica timing sazonal; “pétalas” alinhadas sugerem consistência anual.
A visualização polar (MA3, 2023–2025) evidencia alto alinhamento temporal para VSR (picos entre SE13–18) e Influenza (SE16–21), com maior amplitude em 2025: VSR 1,49/100 mil (SE18) e Influenza 2,25/100 mil (SE21). Já a Covid-19 concentra-se no início do ano (SE8–10), porém com baixa consistência de magnitude—picos mais altos em 2023–2024, elevação secundária em 2023 (SE40–42) e queda acentuada em 2025 (0,68/100 mil).
4 Métricas sazonais (pico, amplitude, duração, centro de gravidade)
Interpretação guiada
semana_pico: quando ocorrem os picos por ano.
duracao_sem: tamanho da “temporada” (semanas ≥ P80).
centro_grav: “média ponderada” do calendário epidêmico.
indice_sazonal: quanto o pico se afasta da média (sazonalidade mais “aguda” = maior valor).
Covid-19: Pico sazonal no início do ano (SE8–9) em 2023–2025; maior pico em 2023 (1,81/100 mil, SE9) e queda marcada em 2025 (0,68/100 mil, SE8). Temporada estável (11 semanas); 2025 teve maior índice de sazonalidade, indicando onda mais aguda apesar da baixa magnitude.
Influenza: Picos no miolo do ano (SE16–21); 2025 apresentou o maior pico (2,25/100 mil, SE21) e o índice sazonal mais alto (5,19), caracterizando temporada mais curta e intensa. Duração: 11–12 semanas.
VSR: Picos precoces (SE13–18) com amplitude crescente (de 0,73 para 1,49/100 mil, 2023→2025) e duração constante (11 semanas). Centro de gravidade ~SE20, anterior ao da Influenza em 2024–2025, sugerindo antecedência temporal.
Em conjunto, 2023–2025 revela sazonalidade consistente: Covid-19 com pico precoce (SE8–9) e menor magnitude recente; VSR abrindo a temporada (SE13–18); Influenza dominando o miolo (SE16–21), com 2025 mais intenso. As temporadas são estáveis (≈11–12 semanas).
4.1 Boxplots comparando diagnósticos
5 Estatística circular (timing dos picos)
Tratamos semana do pico como ângulo no círculo (0, 2π).
Teste de Rayleigh (concentração angular). Avalia se as direções/ângulos se distribuem uniformemente no círculo. Aqui cada semana do pico vira um ângulo; rejeitar H₀ (p < 0,05) implica sazonalidade verdadeira, com picos concentrados no calendário.
Teste de Watson–Williams (ANOVA circular). Compara as médias angulares de grupos (diagnósticos). H₀: os picos médios ocorrem no mesmo momento do ciclo anual. Rejeitar H₀ indica ordem temporal distinta; na Tabela 4a-4b, as colunas por diagnóstico apresentam a média angular (radianos) e a semana epidemiológica correspondente.
Leitura das tabelas
A Tabela 3 confirma sazonalidade significativa para todos os diagnósticos (p < 0,05) e reporta o timing médio dos picos: Covid-19 (SE 8), VSR (SE 16) e Influenza (SE 20).
A Tabela 4 separa o resultado global (estatística F, gl, p) e o resumo por diagnóstico (média angular em radianos/SE), evidenciando que os timings médios diferem (F = 20,081; p = 0,002) e mantendo a ordem temporal Covid-19 → VSR → Influenza.
Por que GAM cíclico? Usamos um modelo aditivo generalizado no qual a incidência semanal é explicada por funções suaves cíclicas da semana epidemiológica (bs = "cc"), permitindo capturar padrões sazonais sem assumir formato paramétrico pré-definido. Cada diagnóstico recebe seu próprio suave e adicionamos um termo de efeito aleatório para o ano, acomodando heterogeneidade interanual residual.
Leitura das tabelas (GAM)
Tabelas 6a–6b: os termos paramétricos capturam diferenças médias entre diagnósticos (referência: Covid-19). Os suavizadores s(semana_epi) específicos obtiveram valores elevados de edf e estatísticas F significativas (p < 0,001), confirmando sazonalidade robusta para Covid-19, Influenza e VSR. O termo aleatório s(ano) apresentou efeito mais discreto.
Tabela 6c: o ajuste explicou ~53% da variabilidade (R² ajustado 0,50; desvio explicado 0,53), reforçando que o componente sazonal domina as séries semanais.
6.1 Curvas previstas por diagnóstico (média nos anos)
Leitura: as curvas suavizadas mostram o “perfil” sazonal médio por diagnóstico e os intervalos de incerteza.
GAM com spline cíclico por semana (2023–2025), o modelo explicou 52,8% da variabilidade (R²aj = 0,50). Os termos sazonais se (semana_epi) foram altamente significativos para Covid-19, Influenza e VSR (p<2e−16), enquanto o efeito de ano não foi significativo (p=0,16). As curvas previstas mostram VSR com pico único na SE≈18, Influenza na SE≈20–22 e Covid-19 com perfil bimodal (pico primário SE 8–10 e secundário SE≈40).
7 Correlação e defasagem entre séries
A seguir calculamos a correlação cruzada (CCF) entre Influenza e VSR, e entre Covid-19 e Influenza, por ano (incidência semanal). Lags positivos significam que a série Y (segunda) ocorre depois da série X (primeira).
7.1 Visualização dos lags máximos e correlações
Interpretação: Nesta parametrização (ccf(dx, dy)), lag_max < 0 indica que diag_y tende a atingir seu pico apósdiag_x (Y fica deslocado para a direita de X). Observe também cor_max, que quantifica a força da associação.
7.2 Leituras numéricas (Tabela 7 / Heatmap)
VSR → Influenza
Defasagem: lag_max = -7, -2, -2 ⇒ Influenza ocorre cerca de 7 semanas após o VSR em 2023 e ~2 semanas depois em 2024–2025.
Força: correlações altas (r = 0,85; 0,71; 0,88).
Covid-19 → VSR
Defasagem: lag_max = -4, -8, -12 ⇒ VSR sucede a Covid-19 em ~4, 8 e 12 semanas (2023–2025).
Síntese temporal 2023–2025: Covid-19 surge primeiro, seguido por VSR (4–12 semanas depois) e, na sequência, Influenza (2–7 semanas após VSR, 8–14 após Covid-19). As correlações são mais altas no elo VSR→Influenza, reforçando a utilidade do VSR como alerta de curto prazo para a temporada de Influenza. Covid-19 permanece como marcador inicial, porém com correlações um pouco menores e mais variáveis entre anos.
Implicações operacionais: Monitorar Covid-19 como indicador de início de temporada respiratória, usar o pico de VSR para planejar respostas rápidas para Influenza (ampliação de leitos, testagem, campanhas). Manter vigilância sobre fatores que possam encurtar/alongar as defasagens.
Notas metodológicas (para transparência):
Séries padronizadas por ano antes do CCF (remove nível/escala).
Janela ±15 semanas; lag>0 significa Y depois de X.
CCF mede associação temporal, não causalidade; sazonalidade compartilhada pode inflar r.
8 Síntese final
Sazonalidade — Os padrões gráficos (Heatmaps e Visualização Polar) e as métricas confirmam sazonalidade consistente para Influenza e VSR. Diferentemente de análises anteriores, o teste de Rayleigh indicou concentração significativa do timing dos picos para todos os três diagnósticos (P-values < 0.05). O Watson–Williams detectou diferença estatística significativa no timing médio dos picos entre diagnósticos (P = 0.002196), com o Covid-19 sendo o mais precoce, seguido pelo VSR e, por fim, pela Influenza.
Timing e intensidade — A média circular dos picos e a análise CCF confirmam que o VSR (pico médio em torno da SE 16) atinge o pico antes da Influenza (pico médio em torno da SE 20). Em 2025, a Influenza exibiu a maior intensidade (pico de 2.25/100k) e o maior índice de sazonalidade (5.19), sugerindo a temporada mais “aguda” do período 2023–2025. A duração das temporadas (duracao_sem) é consistentemente 11 ou 12 semanas para todos os diagnósticos.
Defasagens (CCF) — Entre 2023–2025, observou-se uma ordem temporal sequencial clara: Covid-19 → VSR → Influenza. O VSR consistentemente precede a Influenza por 2 a 7 semanas (correlações fortes, 0.71 a 0.88). O Covid-19 precede o VSR por 4 a 12 semanas (cor: 0.58 a 0.69) e precede a Influenza por 8 a 14 semanas (cor: 0.43 a 0.75).
Modelagem — A Modelagem GAM cíclica se mostrou robusta nesta especificação, com todos os termos suaves sazonais (s(semana_epi)) altamente significativos (p<2e−16). O ajuste do modelo capturou o formato sazonal médio (VSR e Influenza unimodais, Covid-19 bimodal) e explica 52.8% da variabilidade (R2 adj. ≈ 0.502). O termo de efeito aleatório para o ano (s(ano)) não foi estatisticamente significativo (p=0.16), sugerindo que a sazonalidade média domina a variância observada na série.
Covid-19 — No período 2023–2025, o Covid-19 manteve seu pico primário concentrado no início do ano (SE 8–9), com sazonalidade confirmada estatisticamente pelo Teste de Rayleigh. Contudo, a amplitude de incidência variou drasticamente, com picos altos em 2023/2024 e forte queda em 2025 (pico de 0.68/100k).
Implicações operacionais — A sequência de defasagem Covid-19 → VSR → Influenza estabelece janelas de previsão valiosas. O VSR deve ser monitorado como um marcador subsequente ao Covid-19 e antecedente claro do pico de Influenza. Planejar capacidade assistencial e vigilância laboratorial com antecedência de 2 a 7 semanas é crítico para o pico de Influenza, após o pico de VSR. Manter monitoramento semanal é fundamental para capturar variações interanuais na dinâmica de circulação.
Código fonte
---title: "Sazonalidade por Semana Epidemiológica — Covid-19, Influenza e VSR"author: "Unidade de Inteligencia e Vigilancia em Saude (UIVS) - SES/SP"date: todaydate-format: "D [de] MMMM [de] YYYY"lang: pt-BRformat: html: embed-resources: true # HTML autocontido (essencial no RPubs) toc: true toc-depth: 3 number-sections: true smooth-scroll: true code-tools: true # botão para mostrar/ocultar código quando echo=FALSE df-print: paged code-fold: false theme: flatly title-block-banner: false link-external-newwindow: trueeditor: visualexecute: echo: false # esconder código por padrão (usável via code-tools) warning: false message: false cache: false freeze: auto # congela saída até o código mudar (bom p/ rel. estável)---## Objetivo e racionalEste relatório investiga **padrões sazonais semanais** para Covid-19, Influenza e Vírus Sincicial Respiratório (VSR) ao longo dos anos, usando:\- **Incidência semanal por 100 mil hab.** \- **Métricas sazonais** (semana do pico, amplitude, duração da temporada, centro de gravidade temporal).\- **Estatística circular** para comparar o *timing* dos picos entre diagnósticos.\- **Modelagem** com **GAM cíclico** (captura sazonalidade flexível por semana).\- **Correlação e defasagem** entre séries (quem antecipa quem).\- Visualizações: **heatmap** semana×ano, **subseries** por ano, **curvas suavizadas** e **polar**.```{r}#| message: false#| warning: false#| include: false# Pacoteslibrary(dplyr)library(tidyr)library(ggplot2)library(forcats)library(scales)library(readr)library(patchwork)library(viridisLite)library(circular) # estatística circularlibrary(mgcv) # GAMlibrary(zoo) # rollapply (opcional p/ suavização)library(DT) # tabelas interativaslibrary(plotly) # gráficos interativoslibrary(crosstalk) # filtros interativosdf_2022_2025_clean <-readRDS("srag_2022_2025_clean.rds")df_2022_2025_clean <- df_2022_2025_clean |>filter(ano %in%2023:2025)```------------------------------------------------------------------------<br> <br>## Construção da incidência semanalAbaixo calculamos a **incidência semanal agregada** (somando casos e populações municipais por ano) e forçamos a presença de **todas as semanas (1–53)** por diagnóstico×ano para evitar “quebras” nas linhas.```{r}alvos <-c("Covid-19", "Influenza", "Vírus sincicial respiratório")base <- df_2022_2025_clean |>filter(diagnostico %in% alvos, !is.na(pop_total)) |>mutate(semana_epi =as.integer(semana_epi))# População total por ano (soma de pop única por município em cada ano)pop_ano <- base |>distinct(ano, municipio, pop_mun = pop_total) |>group_by(ano) |>summarise(pop_total_ano =sum(pop_mun), .groups ="drop")# Casos por diagnóstico-ano-semana e incidência p/100kincid_agregada_semana <- base |>group_by(diagnostico, ano, semana_epi) |>summarise(casos =n(), .groups ="drop") |>left_join(pop_ano, by ="ano") |>mutate(incid_100k =1e5* casos / pop_total_ano)# Completar semanas ausentes (1–53) e preencher com zerosemana_full <- incid_agregada_semana |>group_by(diagnostico, ano) |> tidyr::complete(semana_epi =1:53,fill =list(casos =0, incid_100k =0)) |>ungroup()# (Opcional) uma série suavizada para gráficossemana_full <- semana_full |>group_by(diagnostico, ano) |>arrange(semana_epi, .by_group =TRUE) |>mutate(incid_100k_ma3 = zoo::rollapply(incid_100k, 3, mean, fill =NA, align ="center")) |>ungroup()datatable( semana_full,extensions ="Buttons",options =list(pageLength =5,scrollX =TRUE,dom ="Bfrtip",buttons =c("copy", "csv", "excel", "print"),columnDefs =list(list(className ="dt-center", targets =0:(ncol(semana_full) -1))) ),filter ="top",rownames =FALSE,caption = htmltools::tags$caption(style ="caption-side: top; text-align: left;","Tabela 1.", htmltools::tags$br(),"Incidência semanal agregada (com MA3) para Covid-19, Influenza e VSR." ))```**Nota de interpretação:** usar a população total anual (soma das populações municipais únicas) evita dupla contagem e padroniza o denominador para comparar semanas dentro do mesmo ano.------------------------------------------------------------------------<br> <br>## Análises descritivas### 1) Subseries (linhas por ano)```{r}gg_subseries <-ggplot(semana_full,aes(x = semana_epi, y = incid_100k,group = ano, color =factor(ano))) +geom_line(alpha = .55) +facet_wrap(~ diagnostico, scales ="free_y", ncol =1) +scale_color_viridis_d(end = .9, option ="C") +labs(title ="Incidência semanal por ano",x ="Semana epidemiológica", y ="Incidência por 100 mil",color ="Ano") +theme_minimal(base_size =12)suppressWarnings(ggplotly( gg_subseries,tooltip =c("diagnostico", "ano", "semana_epi", "incid_100k")))```> **Leitura:** picos recorrentes na mesma janela de semanas indicam **sazonalidade estável**.Os perfis por ano mostram: Entre 2023–2025, os perfis semanais indicam sazonalidade estável para **Influenza** (picos SE16–21; maior amplitude em 2025) e **VSR** (picos SE13–18; amplitude crescente). A **Covid-19** mantém pico precoce consistente (SE8–9), porém com queda acentuada de magnitude até 2025; só 2023 teve elevação tardia (SE40–42). Em suma, estabilidade temporal para Influenza/VSR, variabilidade de magnitude para Covid-19.### 2) Heatmap semana × ano```{r}gg_heat <-ggplot(semana_full,aes(x = semana_epi, y =factor(ano), fill = incid_100k)) +geom_tile() +facet_wrap(~ diagnostico, ncol =1) +scale_fill_viridis_c(option ="D", end = .95, trans ="sqrt", labels =label_number(accuracy =0.1)) +labs(title ="Heatmap — Incidência semanal (p/100k)",x ="Semana", y ="Ano", fill ="Incidência") +theme_minimal(base_size =12)gg_heat```> **Leitura:** faixas verticais mais intensas indicam **períodos de maior risco** por ano.Os heatmaps de 2023–2025 mostram “janelas quentes” claras: **Influenza** concentra-se no miolo do ano (SE15–26), com pico mais intenso em 2025 (SE21, 2,25/100 mil); o **VSR** antecipa essa janela (SE12–18), com padrão altamente consistente e intensidade crescente até 2025 (SE18, 1,49/100 mil). Já a **Covid-19** concentra-se no início do ano (SE1–10), apresenta manchas menos regulares, um aumento tardio em 2023 (SE40–42) e queda marcante de magnitude em 2025 (pico de 0,68/100 mil).### 3) Polar (visão circular do ano)```{r}polar_data <- semana_full |>mutate(theta =360* (semana_epi /53),ano =factor(ano),hover_txt =paste0("<b>", diagnostico, "</b>","<br>Ano: ", ano,"<br>Semana: ", semana_epi,"<br>Incid. (MA3): ", scales::number(incid_100k_ma3, accuracy =0.01) ) )shared_polar <- SharedData$new(polar_data, group ="polar")filtros_polar <- htmltools::div(class ="mb-3", htmltools::tags$strong("Filtros interativos:"),filter_checkbox(id ="polar_diag",label ="Diagnósticos",sharedData = shared_polar,group =~diagnostico,inline =TRUE ),filter_checkbox(id ="polar_ano",label ="Anos",sharedData = shared_polar,group =~ano,inline =TRUE ))cores_diag <-c("Covid-19"="#d73027","Influenza"="#1a9850","Vírus sincicial respiratório"="#4575b4")polar_plot <-plot_ly(data = shared_polar,type ="scatterpolar",mode ="lines",theta =~theta,r =~incid_100k_ma3,split =~interaction(diagnostico, ano, drop =TRUE),color =~diagnostico,colors = cores_diag,text =~hover_txt,hoverinfo ="text",line =list(width =1.2),showlegend =FALSE) |>layout(title ="Visão polar — Incidência suavizada (MA3)",polar =list(radialaxis =list(title ="", gridcolor ="#dddddd"),angularaxis =list(direction ="counterclockwise", rotation =90) ),margin =list(t =80) )htmltools::tagList(filtros_polar, polar_plot)```*Use os filtros acima para escolher quais diagnósticos e anos deseja visualizar simultaneamente.*> **Leitura:** o ângulo (semana) do maior raio indica **timing** sazonal; “pétalas” alinhadas sugerem consistência anual.A visualização polar (MA3, 2023–2025) evidencia alto alinhamento temporal para **VSR** (picos entre SE13–18) e **Influenza** (SE16–21), com maior amplitude em 2025: **VSR** 1,49/100 mil (SE18) e **Influenza** 2,25/100 mil (SE21). Já a **Covid-19** concentra-se no início do ano (SE8–10), porém com baixa consistência de magnitude—picos mais altos em 2023–2024, elevação secundária em 2023 (SE40–42) e queda acentuada em 2025 (0,68/100 mil).------------------------------------------------------------------------<br> <br>## Métricas sazonais (pico, amplitude, duração, centro de gravidade)```{r}met <- semana_full |>group_by(diagnostico, ano) |>summarise(semana_pico = semana_epi[which.max(incid_100k)],pico_100k =max(incid_100k, na.rm =TRUE),media_100k =mean(incid_100k),mediana_100k =median(incid_100k),amplitude = pico_100k - mediana_100k,limiar =quantile(incid_100k, .80, na.rm =TRUE),duracao_sem =sum(incid_100k >= limiar),centro_grav =sum(semana_epi * incid_100k)/sum(incid_100k),.groups ="drop" ) |>mutate(indice_sazonal = pico_100k /pmax(media_100k, 1e-9))met_table <- met |>arrange(diagnostico, ano)datatable( met_table,extensions ="Buttons",options =list(pageLength =9,scrollX =TRUE,dom ="Bfrtip",buttons =c("copy", "csv", "excel", "print"),columnDefs =list(list(className ="dt-center", targets =0:(ncol(met_table) -1)) ) ),filter ="top",rownames =FALSE,caption = htmltools::tags$caption(style ="caption-side: top; text-align: left;","Tabela 2.", htmltools::tags$br(),"Métricas sazonais por diagnóstico e ano (pico, amplitude, duração, centro de gravidade e índice sazonal)." ))```**Interpretação guiada**- `semana_pico`: quando ocorrem os picos por ano.- `duracao_sem`: tamanho da “temporada” (semanas ≥ P80).- `centro_grav`: “média ponderada” do calendário epidêmico.- `indice_sazonal`: quanto o pico se afasta da média (sazonalidade mais “aguda” = maior valor).**Covid-19:** Pico sazonal no início do ano (SE8–9) em 2023–2025; maior pico em 2023 (1,81/100 mil, SE9) e queda marcada em 2025 (0,68/100 mil, SE8). Temporada estável (11 semanas); 2025 teve maior índice de sazonalidade, indicando onda mais aguda apesar da baixa magnitude.**Influenza:** Picos no miolo do ano (SE16–21); 2025 apresentou o maior pico (2,25/100 mil, SE21) e o índice sazonal mais alto (5,19), caracterizando temporada mais curta e intensa. Duração: 11–12 semanas.**VSR:** Picos precoces (SE13–18) com amplitude crescente (de 0,73 para 1,49/100 mil, 2023→2025) e duração constante (11 semanas). Centro de gravidade \~SE20, anterior ao da Influenza em 2024–2025, sugerindo antecedência temporal.Em conjunto, 2023–2025 revela sazonalidade consistente: **Covid-19** com pico precoce (SE8–9) e menor magnitude recente; **VSR** abrindo a temporada (SE13–18); **Influenza** dominando o miolo (SE16–21), com 2025 mais intenso. As temporadas são estáveis (≈11–12 semanas).### Boxplots comparando diagnósticos```{r}p1 <-ggplot(met, aes(diagnostico, semana_pico, fill = diagnostico)) +geom_boxplot(alpha = .8) +labs(title ="Distribuição da semana do pico por diagnóstico",x =NULL, y ="Semana do pico") +theme_minimal(base_size =12) +theme(legend.position ="none")p2 <-ggplot(met, aes(diagnostico, duracao_sem, fill = diagnostico)) +geom_boxplot(alpha = .8) +labs(title ="Duração da temporada (semanas ≥ P80)",x =NULL, y ="Semanas") +theme_minimal(base_size =12) +theme(legend.position ="none")p3 <-ggplot(met, aes(diagnostico, indice_sazonal, fill = diagnostico)) +geom_boxplot(alpha = .8) +labs(title ="Índice de sazonalidade (pico / média)",x =NULL, y ="Razão") +theme_minimal(base_size =12) +theme(legend.position ="none")p1 / p2 / p3```------------------------------------------------------------------------<br> <br>## Estatística circular (timing dos picos)Tratamos **semana do pico** como ângulo no círculo (0, 2π).> **Teste de Rayleigh (concentração angular).** Avalia se as direções/ângulos se distribuem uniformemente no círculo. Aqui cada semana do pico vira um ângulo; rejeitar H₀ (p \< 0,05) implica sazonalidade verdadeira, com picos concentrados no calendário.```{r}picos_circ <- met |>transmute( diagnostico, ano,theta =circular(2*pi*semana_pico/52, type ="angles", units ="radians", template ="none") )rayleigh_summary <- picos_circ |>group_by(diagnostico) |>group_modify(~{ test <-rayleigh.test(.x$theta) media_theta <-mean.circular(.x$theta) semana_media <- (as.numeric(media_theta) %% (2*pi)) / (2*pi) *52tibble(rayleigh_z =unname(test$statistic),p_valor = test$p.value,semana_media = semana_media,theta_media =as.numeric(media_theta) ) }) |>ungroup() |>mutate(semana_media =ifelse(semana_media <=0, semana_media +52, semana_media),ordem =rank(semana_media) )rayleigh_dt <-datatable( rayleigh_summary |>transmute( Diagnóstico = diagnostico,`Rayleigh z`= rayleigh_z,`p-valor`= p_valor,`Semana média do pico (SE)`= semana_media ),extensions ="Buttons",options =list(pageLength =3,dom ="Bfrtip",buttons =c("copy", "csv", "excel", "print") ),rownames =FALSE,caption = htmltools::tags$caption(style ="caption-side: top; text-align: left;","Tabela 3.", htmltools::tags$br(),"Teste de Rayleigh por diagnóstico — estatística z, p-valor e semana média do pico (2023–2025)." )) |>formatRound(columns =c("Rayleigh z", "p-valor", "Semana média do pico (SE)"), digits =3)ww <-watson.williams.test(theta ~ diagnostico, data =as.data.frame(picos_circ))ww_stats <-tibble(`Estatística F`=unname(ww$statistic["F"]),`gl (numerador)`= ww$parameter[1],`gl (denominador)`= ww$parameter[2],`p-valor`= ww$p.value)ww_diag <- rayleigh_summary |>transmute( Diagnóstico = diagnostico,`Média angular (rad)`= theta_media %% (2*pi),`Semana média (SE)`= semana_media )ww_stats_dt <-datatable( ww_stats,options =list(dom ="t", ordering =FALSE, pageLength =1),rownames =FALSE,caption = htmltools::tags$caption(style ="caption-side: top; text-align: left;","Tabela 4a.", htmltools::tags$br(),"Teste Watson–Williams — estatística F, graus de liberdade e p-valor." )) |>formatRound(columns =c("Estatística F", "p-valor"), digits =3)ww_diag_dt <-datatable( ww_diag,options =list(dom ="t", ordering =FALSE, pageLength =3),rownames =FALSE,caption = htmltools::tags$caption(style ="caption-side: top; text-align: left;","Tabela 4b", htmltools::tags$br(),"Diagnósticos – média angular e semana correspondente." )) |>formatRound(columns =c("Média angular (rad)", "Semana média (SE)"), digits =3)rayleigh_dt```<br>> **Teste de Watson–Williams (ANOVA circular).** Compara as médias angulares de grupos (diagnósticos). H₀: os picos médios ocorrem no mesmo momento do ciclo anual. Rejeitar H₀ indica ordem temporal distinta; na Tabela 4a-4b, as colunas por diagnóstico apresentam a média angular (radianos) e a semana epidemiológica correspondente.```{r}htmltools::tagList(ww_stats_dt, ww_diag_dt)```**Leitura das tabelas**- A **Tabela 3** confirma sazonalidade significativa para todos os diagnósticos (p \< 0,05) e reporta o timing médio dos picos: Covid-19 (SE 8), VSR (SE 16) e Influenza (SE 20).- A **Tabela 4** separa o resultado global (estatística F, gl, p) e o resumo por diagnóstico (média angular em radianos/SE), evidenciando que os timings médios diferem (F = 20,081; p = 0,002) e mantendo a ordem temporal Covid-19 → VSR → Influenza.------------------------------------------------------------------------<br> <br>## Modelagem com GAM cíclico (semana \~ s(. , bs = "cc"))> **Por que GAM cíclico?** Usamos um modelo aditivo generalizado no qual a incidência semanal é explicada por funções suaves cíclicas da semana epidemiológica (`bs = "cc"`), permitindo capturar padrões sazonais sem assumir formato paramétrico pré-definido. Cada diagnóstico recebe seu próprio suave e adicionamos um termo de efeito aleatório para o ano, acomodando heterogeneidade interanual residual.```{r}# Remover combinações totalmente zeradas (opcional)dat_gam <- semana_full# Ajuste do GAM — um suave por diagnóstico (via interação por "by")gam_fit <-gam( incid_100k ~ diagnostico +s(semana_epi, bs ="cc", k =20, by = diagnostico) +s(ano, bs ="re"),data = dat_gam,method ="REML")``````{r}gam_summary <-summary(gam_fit)gam_param <- gam_summary$p.table |>as.data.frame()gam_param$Termo <-rownames(gam_summary$p.table)gam_param <- gam_param[, c("Termo", "Estimate", "Std. Error", "t value", "Pr(>|t|)")]rownames(gam_param) <-NULLnames(gam_param) <-c("Termo", "Estimativa", "Erro padrão", "t", "p-valor")gam_smooth <- gam_summary$s.table |>as.data.frame()gam_smooth$`Termo suave`<-rownames(gam_summary$s.table)gam_smooth <- gam_smooth[, c("Termo suave", "edf", "Ref.df", "F", "p-value")]rownames(gam_smooth) <-NULLnames(gam_smooth) <-c("Termo suave", "edf", "Ref.df", "Estatística F", "p-valor")gam_perf <-data.frame(`R² ajustado`= gam_summary$r.sq,`Desvio explicado`= gam_summary$dev.expl,`Escala (phi)`= gam_summary$scale,`N`= gam_summary$n)colnames(gam_perf) <-c("R² ajustado", "Desvio explicado", "Escala (phi)", "N")gam_param_tbl <-datatable( gam_param,options =list(dom ="t", ordering =FALSE, pageLength =nrow(gam_param)),rownames =FALSE,caption = htmltools::tags$caption(style ="caption-side: top; text-align: left;","Tabela 6a.", htmltools::tags$br(),"Coeficientes paramétricos (referência = Covid-19)." )) |>formatRound(columns =c("Estimativa", "Erro padrão", "t", "p-valor"), digits =3)gam_smooth_tbl <-datatable( gam_smooth,options =list(dom ="t", ordering =FALSE, pageLength =nrow(gam_smooth)),rownames =FALSE,caption = htmltools::tags$caption(style ="caption-side: top; text-align: left;","Tabela 6b.", htmltools::tags$br(),"Termos suaves do GAM cíclico (por diagnóstico e efeito anual)." )) |>formatRound(columns =c("edf", "Ref.df", "Estatística F", "p-valor"), digits =3)gam_perf_tbl <-datatable( gam_perf,options =list(dom ="t", ordering =FALSE, pageLength =1),rownames =FALSE,caption = htmltools::tags$caption(style ="caption-side: top; text-align: left;","Tabela 6c.", htmltools::tags$br(),"Indicadores globais do ajuste (GAM cíclico)." )) |>formatRound(columns =c("R² ajustado", "Desvio explicado", "Escala (phi)"), digits =3)htmltools::tagList(gam_param_tbl, gam_smooth_tbl, gam_perf_tbl)```**Leitura das tabelas (GAM)**- **Tabelas 6a–6b**: os termos paramétricos capturam diferenças médias entre diagnósticos (referência: Covid-19). Os suavizadores `s(semana_epi)` específicos obtiveram valores elevados de `edf` e estatísticas F significativas (p \< 0,001), confirmando sazonalidade robusta para Covid-19, Influenza e VSR. O termo aleatório `s(ano)` apresentou efeito mais discreto.- **Tabela 6c**: o ajuste explicou ~53% da variabilidade (R² ajustado 0,50; desvio explicado 0,53), reforçando que o componente sazonal domina as séries semanais.### Curvas previstas por diagnóstico (média nos anos)```{r}newdat <-expand.grid(semana_epi =1:53,diagnostico =levels(factor(dat_gam$diagnostico)),ano =median(dat_gam$ano, na.rm =TRUE) # ano de referência p/ termo aleatório)pred <-predict(gam_fit, newdata = newdat, se.fit =TRUE)newdat$fit <- pred$fitnewdat$se <- pred$se.fitnewdat$lo <-pmax(newdat$fit -1.96*newdat$se, 0)newdat$hi <- newdat$fit +1.96*newdat$segg_gam <-ggplot(newdat, aes(semana_epi, fit, color = diagnostico)) +geom_ribbon(aes(ymin = lo, ymax = hi, fill = diagnostico), alpha = .15, color =NA) +geom_line(size =1) +facet_wrap(~ diagnostico, scales ="free_y", ncol =1) +labs(title ="Curvas GAM cíclicas por diagnóstico",x ="Semana", y ="Incidência prevista (p/100 mil)") +theme_minimal(base_size =12)gg_gam```> **Leitura:** as curvas suavizadas mostram o “perfil” sazonal médio por diagnóstico e os **intervalos de incerteza**.GAM com spline cíclico por semana (2023–2025), o modelo explicou 52,8% da variabilidade (R²aj = 0,50). Os termos sazonais se (semana_epi) foram altamente significativos para **Covid-19**, **Influenza** e **VSR** (p\<2e−16), enquanto o efeito de ano não foi significativo (p=0,16). As curvas previstas mostram **VSR** com pico único na SE≈18, **Influenza** na SE≈20–22 e **Covid-19** com perfil bimodal (pico primário SE 8–10 e secundário SE≈40).------------------------------------------------------------------------<br> <br>## Correlação e defasagem entre sériesA seguir calculamos a **correlação cruzada (CCF)** entre Influenza e VSR, e entre Covid-19 e Influenza, por ano (incidência semanal). Lags positivos significam que a **série Y** (segunda) **ocorre depois** da série X (primeira).```{r}library(dplyr)library(purrr)ccf_by_year <-function(df, diag_x, diag_y, lag_max =15, standardize =TRUE) { anos <-sort(unique(df$ano)) out <-vector("list", length(anos))for (i inseq_along(anos)) { a <- anos[i] dx <- df |>filter(diagnostico == diag_x, ano == a) |>arrange(semana_epi) |>pull(incid_100k) dy <- df |>filter(diagnostico == diag_y, ano == a) |>arrange(semana_epi) |>pull(incid_100k)# checagensif (length(dx) ==length(dy) &&length(dx) >10&&all(is.finite(dx+dy))) {# padroniza séries (opcional) para tirar nível/escala do anoif (standardize) { dx <-as.numeric(scale(dx)) dy <-as.numeric(scale(dy)) }# garante lag.max válido para o tamanho da série lag_max_eff <-max(0, min(lag_max, length(dx) -1)) cc <-ccf(dx, dy, plot =FALSE, lag.max = lag_max_eff, na.action = na.omit) idx <-which.max(cc$acf) lag_atmax <-as.numeric(cc$lag[idx]) # este é o lag do pico da CCF cor_atmax <-as.numeric(cc$acf[idx]) out[[i]] <-data.frame(ano = a, diag_x = diag_x, diag_y = diag_y,lag_max = lag_atmax, cor_max = cor_atmax ) } else { out[[i]] <-NULL } } dplyr::bind_rows(out)}diags <-c("Covid-19", "Influenza", "Vírus sincicial respiratório")ordem_diag <-c("Covid-19", "Vírus sincicial respiratório", "Influenza")pares <-expand.grid(diag_x = diags, diag_y = diags, stringsAsFactors =FALSE) |>filter(diag_x != diag_y) |>mutate(idx_x =match(diag_x, ordem_diag),idx_y =match(diag_y, ordem_diag) ) |>filter(!is.na(idx_x), !is.na(idx_y), idx_x < idx_y) |>select(diag_x, diag_y)ccf_all <- purrr::map2_dfr(pares$diag_x, pares$diag_y,~ccf_by_year(semana_full, .x, .y, lag_max =15, standardize =TRUE)) |>arrange(diag_x, diag_y, ano) |>filter(cor_max >=0)datatable( ccf_all,extensions ="Buttons",options =list(pageLength =9,scrollX =TRUE,dom ="Bfrtip",buttons =c("copy", "csv", "excel", "print"),columnDefs =list(list(className ="dt-center", targets =0:(ncol(ccf_all) -1)) ) ),filter ="top",rownames =FALSE,caption = htmltools::tags$caption(style ="caption-side: top; text-align: left;","Tabela 7.", htmltools::tags$br(),"Correlação cruzada por par de diagnósticos: lag do pico (semanas) e correlação máxima por ano." ))```### Visualização dos lags máximos e correlações```{r}ccf_plot <- ccf_all |>mutate(par =paste(diag_x, "→", diag_y),lbl =sprintf("lag=%+d\nr=%.2f", lag_max, cor_max))ggplot(ccf_plot, aes(x = ano, y =factor(par, levels =unique(par)), fill = lag_max)) +geom_tile() +geom_text(aes(label = lbl), size =3) +scale_fill_gradient2(low ="#4575b4", mid ="white", high ="#d73027",midpoint =0, name ="Lag (semanas)") +labs(title ="CCF por ano: lag máximo e correlação",x ="Ano", y ="Par (X → Y)") +theme_minimal()```> **Interpretação:** Nesta parametrização (`ccf(dx, dy)`), `lag_max < 0` indica que **diag_y** tende a atingir seu pico **após** **diag_x** (Y fica deslocado para a direita de X). Observe também `cor_max`, que quantifica a força da associação.### Leituras numéricas (Tabela 7 / Heatmap)1. **VSR → Influenza** - Defasagem: `lag_max = -7`, `-2`, `-2` ⇒ Influenza ocorre cerca de 7 semanas após o VSR em 2023 e ~2 semanas depois em 2024–2025. - Força: correlações altas (r = 0,85; 0,71; 0,88).2. **Covid-19 → VSR** - Defasagem: `lag_max = -4`, `-8`, `-12` ⇒ VSR sucede a Covid-19 em ~4, 8 e 12 semanas (2023–2025). - Força: associações moderadas/fortes (r = 0,58; 0,68; 0,69).3. **Covid-19 → Influenza** - Defasagem: `lag_max = -12`, `-8`, `-14` ⇒ Influenza vem 8–14 semanas após Covid-19 (variação anual). - Força: moderada a forte (r = 0,62; 0,43; 0,75).**Síntese temporal 2023–2025:** Covid-19 surge primeiro, seguido por VSR (4–12 semanas depois) e, na sequência, Influenza (2–7 semanas após VSR, 8–14 após Covid-19). As correlações são mais altas no elo VSR→Influenza, reforçando a utilidade do VSR como alerta de curto prazo para a temporada de Influenza. Covid-19 permanece como marcador inicial, porém com correlações um pouco menores e mais variáveis entre anos.**Implicações operacionais:** Monitorar Covid-19 como indicador de início de temporada respiratória, usar o pico de VSR para planejar respostas rápidas para Influenza (ampliação de leitos, testagem, campanhas). Manter vigilância sobre fatores que possam encurtar/alongar as defasagens.**Notas metodológicas (para transparência):**- Séries **padronizadas por ano** antes do CCF (remove nível/escala).- Janela **±15 semanas**; lag\>0 significa **Y depois de X**.- CCF mede **associação temporal**, **não causalidade**; sazonalidade compartilhada pode inflar *r*.------------------------------------------------------------------------<br> <br>## Síntese final1. **Sazonalidade** — Os padrões gráficos (Heatmaps e Visualização Polar) e as métricas confirmam sazonalidade consistente para **Influenza** e **VSR**. Diferentemente de análises anteriores, o teste de **Rayleigh** indicou concentração significativa do **timing** dos picos para todos os três diagnósticos (P-values \< 0.05). O **Watson–Williams** detectou diferença estatística significativa no **timing** médio dos picos entre diagnósticos (P = 0.002196), com o **Covid-19** sendo o mais precoce, seguido pelo **VSR** e, por fim, pela **Influenza**.2. **Timing e intensidade** — A média circular dos picos e a análise **CCF** confirmam que o **VSR** (pico médio em torno da SE 16) atinge o pico antes da **Influenza** (pico médio em torno da SE 20). Em 2025, a **Influenza** exibiu a maior intensidade (pico de 2.25/100k) e o maior índice de sazonalidade (5.19), sugerindo a temporada mais "aguda" do período 2023–2025. A duração das temporadas (duracao_sem) é consistentemente 11 ou 12 semanas para todos os diagnósticos.3. **Defasagens (CCF)** — Entre **2023–2025**, observou-se uma ordem temporal sequencial clara: **Covid-19 → VSR → Influenza**. O **VSR** consistentemente precede a **Influenza** por 2 a 7 semanas (correlações fortes, 0.71 a 0.88). O **Covid-19** precede o **VSR** por 4 a 12 semanas (cor: 0.58 a 0.69) e precede a **Influenza** por 8 a 14 semanas (cor: 0.43 a 0.75).4. **Modelagem** — A **Modelagem GAM cíclica** se mostrou robusta nesta especificação, com todos os termos suaves sazonais (s(semana_epi)) **altamente significativos (p\<2e−16)**. O ajuste do modelo capturou o formato sazonal médio (VSR e Influenza unimodais, Covid-19 bimodal) e explica **52.8%** da variabilidade (R2 adj. ≈ 0.502). O termo de efeito aleatório para o ano (s(ano)) não foi estatisticamente significativo (p=0.16), sugerindo que a sazonalidade média domina a variância observada na série.5. **Covid-19** — No período 2023–2025, o **Covid-19** manteve seu pico primário concentrado no **início do ano (SE 8–9)**, com sazonalidade confirmada estatisticamente pelo Teste de **Rayleigh**. Contudo, a amplitude de incidência variou drasticamente, com picos altos em 2023/2024 e forte queda em 2025 (pico de 0.68/100k).6. **Implicações operacionais** — A sequência de defasagem **Covid-19 → VSR → Influenza** estabelece janelas de previsão valiosas. O **VSR** deve ser monitorado como um marcador subsequente ao **Covid-19** e antecedente claro do pico de **Influenza**. Planejar capacidade assistencial e vigilância laboratorial com antecedência de 2 a 7 semanas é crítico para o pico de **Influenza**, após o pico de **VSR**. Manter monitoramento semanal é fundamental para capturar variações interanuais na dinâmica de circulação.------------------------------------------------------------------------