A vacinação contra a COVID-19 representou uma das maiores campanhas de saúde pública da história recente. Em Recife, capital pernambucana com cerca de 1,5 milhão de habitantes, a campanha mobilizou dezenas de unidades de saúde e resultou na aplicação de milhões de doses, englobando esquemas primários e de reforço. Compreender o perfil dessa mobilização (identificando quem foi vacinado, quando, com qual imunobiológico e em qual região da cidade) é fundamental para extrair lições que possam orientar futuras ações de imunização em larga escala.
Os dados analisados neste relatório foram obtidos no Portal de Dados Abertos da Prefeitura do Recife e abrangem os registros de vacinação contra a COVID-19 consolidados pela plataforma Conecta Recife ao longo do ano de 2022. O estudo segue uma metodologia estruturada em quatro etapas consecutivas: a importação e o diagnóstico estrutural da base bruta; o processo de limpeza e transformação de dados, que incluiu a separação de campos compostos e a padronização de variáveis de interesse; a análise exploratória conduzida sob múltiplas dimensões (temporal, demográfica e geográfica) e, por fim, o enriquecimento analítico por meio do cruzamento com denominadores populacionais locais para o cálculo de taxas de cobertura vacinal.
No aspecto técnico, toda a pesquisa e manipulação de dados foram desenvolvidas na linguagem R. O pipeline utiliza o ecossistema tidyverse para as operações de transformação e engenharia de dados, o pacote lubridate para o processamento de variáveis de tempo, e bibliotecas como plotly, leaflet, DT e kableExtra para a produção de tabelas e visualizações interativas. Variáveis derivadas foram criadas ao longo do pipeline, tais como distrito, unidade, distrito_cod, mes_vacinacao, dia_semana e cobertura, com o propósito de ampliar a capacidade analítica da base. A operação de left_join foi empregada como recurso central para acoplar as contagens de doses administradas no município às tabelas de referência demográfica do Censo 2022 do IBGE, permitindo uma contextualização real e padronizada das taxas de imunização no território recifense.
Os resultados obtidos a partir dessa abordagem oferecem um diagnóstico espacial, temporal e populacional robusto sobre o desenvolvimento da campanha no território recifense. Essas análises e indicadores servem de subsídio estratégico para prefeitos, secretários de saúde, gestores públicos e epidemiologistas, auxiliando na tomada de decisões baseadas em evidências para o planejamento e a otimização de futuras ações de imunização em larga escala, bem como na identificação de gargalos de adesão e de pontos de vulnerabilidade que demandem o acompanhamento contínuo da gestão municipal.
Para o desenvolvimento deste relatório, foram utilizados os seguintes pacotes da linguagem R:
| Pacote | Utilização |
|---|---|
| tidyverse | Manipulação, limpeza e visualização de dados (dplyr, ggplot2, etc.). |
| lubridate | Tratamento e análise de variáveis temporais (datas). |
| plotly | Conversão de gráficos estáticos em visualizações interativas. |
| scales | Formatação de escalas, eixos e legendas dos gráficos. |
| DT | Geração de tabelas HTML interativas com paginação e busca. |
| knitr | Renderização do relatório R Markdown e tabelas estáticas. |
| kableExtra | Estilização avançada e personalização estética de tabelas. |
| sf | Manipulação de dados geográficos (Simple Features). |
| leaflet | Criação de mapas interativos para visualização geoespacial. |
Os dados utilizados neste projeto foram obtidos no Portal de Dados Abertos da Prefeitura do Recife, sob o conjunto denominado Perfil das Pessoas Vacinadas - Covid-19. Trata-se de registros administrativos gerados pela plataforma Conecta Recife, que centralizou o agendamento e o acompanhamento digital das doses aplicadas no município.
O dataset original foi coletado ao longo de toda a campanha de vacinação contra a COVID-19 em Recife e contém registros individuais de cada dose aplicada. O arquivo CSV disponibilizado possui 1.466.348 registros e 13 variáveis.
## Rows: 1,466,348
## Columns: 13
## $ faixa_etaria <chr> "35 a 39 anos", "35 a 39 anos", "20 a 24 anos", "35 …
## $ idade <dbl> 36, 37, 20, 38, 26, 31, 35, 47, 36, 45, 37, 44, 43, …
## $ sexo <chr> "FEMININO", "MASCULINO", "MASCULINO", "MASCULINO", "…
## $ raca_cor <chr> "PARDA", "BRANCA", "BRANCA", "PARDA", "BRANCA", "PAR…
## $ municipio <chr> "RECIFE", "RECIFE", "RECIFE", "RECIFE", "RECIFE", "R…
## $ grupo <chr> "TRABALHADORES DA SAÚDE", "PESSOAS COM COMORBIDADES"…
## $ categoria <chr> NA, "PESSOAS COM OBESIDADE MÓRBIDA (IMC > OU = 40)",…
## $ lote <chr> "FM2951", "FK8911", "FL4222", "219VCD273Z", "FM2967"…
## $ vacina_fabricante <chr> "3 - COMIRNATY (PFIZER)", "3 - COMIRNATY (PFIZER)", …
## $ descricao_dose <dbl> 3, 3, 3, 3, 3, 3, 3, 1, 3, 2, 3, 3, 3, 3, 3, 2, 3, 3…
## $ cnes <chr> "DS 1: CNES: 000507 - POLICLÍNICA GOUVEIA DE BARROS"…
## $ sistema_origem <chr> "Conecta Recife", "Conecta Recife", "Conecta Recife"…
## $ data_vacinacao <dttm> 2022-01-24, 2022-01-11, 2022-01-08, 2022-02-18, 202…
Antes de iniciar as transformações, é essencial compreender a estrutura dos dados brutos e suas peculiaridades. O arquivo CSV apresenta as seguintes características:
faixa_etaria,
idade, sexo, raca_cor):
Representam o perfil do vacinado. Note que a coluna
raca_cor possui inconsistências de digitação (como
"ÍNDÍGENA" ou "ÍNDIGENA") e a string
"NÃO INFORMADO", que no arquivo original é apenas um texto
comum, mas semanticamente atua como um dado ausente (NA).municipio,
grupo, categoria, lote,
vacina_fabricante, descricao_dose,
cnes, sistema_origem): Detalham o contexto da
aplicação.
categoria tem uma altíssima prevalência de
valores ausentes formais. Isso não é um erro de qualidade, mas uma
característica estrutural, já que a imensa maioria do público se vacinou
pelo critério de idade e não por uma categoria profissional ou de
comorbidade específica.cnes combina o distrito sanitário e o nome da
unidade de saúde em uma única string extensa e redundante.vacina_fabricante traz prefixos numéricos
codificados junto ao nome do laboratório.data_vacinacao): Registra o
momento da aplicação da dose. Originalmente, a variável é importada como
texto (caractere) com o horário zerado (ex:
"2022-01-24 00:00:00.0"), o que exigirá conversão para o
formato apropriado de data.A tabela a seguir apresenta o resumo estrutural do dataset
exatamente como foi importado, evidenciando o status
inicial dos valores ausentes (NAs explícitos) e a tipagem original
(predominantemente character).
resumo_raw <- tibble(
Variável = names(vacina_raw),
Tipo = sapply(vacina_raw, \(x) class(x)[1]),
`Valores Únicos` = sapply(vacina_raw, n_distinct),
`NAs (%)` = sapply(vacina_raw, \(x) scales::percent(mean(is.na(x)), accuracy = 0.01)),
`Exemplo` = sapply(vacina_raw, \(x) {
val <- na.omit(x)[1]
if (is.null(val) || length(val) == 0) return("-")
as.character(val)
})
)
resumo_raw |>
kable(align = "llccl") |>
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE,
font_size = 13
) |>
column_spec(1, bold = TRUE) |>
column_spec(4, color = ifelse(
grepl("^0\\.00%$", resumo_raw$`NAs (%)`), "#27ae60", "#e74c3c"
))| Variável | Tipo | Valores Únicos | NAs (%) | Exemplo |
|---|---|---|---|---|
| faixa_etaria | character | 22 | 0.00% | 35 a 39 anos |
| idade | numeric | 121 | 0.00% | 36 |
| sexo | character | 4 | 0.00% | FEMININO |
| raca_cor | character | 8 | 0.02% | PARDA |
| municipio | character | 611 | 0.00% | RECIFE |
| grupo | character | 29 | 0.00% | TRABALHADORES DA SAÚDE |
| categoria | character | 170 | 88.90% | PESSOAS COM OBESIDADE MÓRBIDA (IMC > OU = 40) |
| lote | character | 662 | 0.07% | FM2951 |
| vacina_fabricante | character | 7 | 0.00% | 3 - COMIRNATY (PFIZER) |
| descricao_dose | numeric | 6 | 0.00% | 3 |
| cnes | character | 8 | 0.00% | DS 1: CNES: 000507 - POLICLÍNICA GOUVEIA DE BARROS |
| sistema_origem | character | 2 | 0.00% | Conecta Recife |
| data_vacinacao | POSIXct | 361 | 0.00% | 2022-01-24 |
O primeiro passo é restringir o conjunto ao município de Recife. Embora o dataset seja da prefeitura, há 41978 registros de outros municípios, representando pessoas que se vacinaram em Recife mas têm cadastro em outra cidade. Como o foco da análise é o perfil da campanha em Recife, esses registros são removidos.
A coluna vacina_fabricante contém um prefixo numérico no
formato "N - " (ex.: "85 - PFIZER"). Esse
prefixo é removido para que o campo reflita apenas o nome do
laboratório, facilitando agrupamentos e visualizações.
A variável raca_cor apresenta duas inconsistências: a
grafia alternativa "ÍNDÍGENA" (com acentos incorretos) e o
valor "NÃO INFORMADO", que é convertido para
NA por não representar uma categoria analítica válida.
A coluna cnes agrega duas informações em um único campo
textual: o distrito sanitário (no padrão "DS N") e o nome
da unidade de saúde. Ambas são extraídas via expressão regular para
colunas separadas (distrito e unidade), e a
coluna original é descartada.
A coluna data_vacinacao é convertida para o tipo
Date. Em seguida, é derivada a coluna
mes_vacinacao, truncando a data ao primeiro dia do mês
correspondente, o que permite agregar registros por período mensal nas
análises temporais.
A coluna descricao_dose é filtrada para remover a dose
6, que possui apenas 1 registro no ano de 2022, e em seguida é
recodificada de valores inteiros (1 a 5) para um fator ordenado com
rótulos descritivos ("1ª Dose", "2ª Dose",
"1º Reforço", "2º Reforço",
"3º Reforço"). O uso de factor garante
ordenação correta nos gráficos e tabelas.
Para possibilitar a junção dos dados de vacinação com o arquivo
geoespacial dos distritos sanitários de Recife (GeoJSON), é extraído o
número do distrito da coluna textual distrito e armazenado
como inteiro na nova coluna distrito_cod.
Para calcular taxas de cobertura vacinal, os dados de vacinação foram cruzados com estimativas populacionais do Censo Demográfico 2022, obtidas diretamente do portal SIDRA do IBGE. Foram utilizadas duas tabelas: a Tabela 9514 (população por faixa etária e sexo) e a Tabela 9606 (população por faixa etária e raça/cor), ambas filtradas para o município de Recife (código 2611606).
Os dados populacionais são estruturados em quatro tibbles de referência, cada um representando um nível de desagregação: população total por faixa etária, desagregada por sexo, por raça/cor, e pela combinação de faixa etária com raça/cor. Essa estrutura permite calcular taxas de cobertura em diferentes dimensões.
Referência de denominador para o cálculo de cobertura geral. Cobre
todas as 21 faixas etárias quinquenais do Censo 2022, da faixa
"0 a 4 anos" até "100 anos +".
pop_faixa <- tibble(
faixa_etaria = c(
"0 a 4 anos", "5 a 9 anos", "10 a 14 anos", "15 a 19 anos",
"20 a 24 anos", "25 a 29 anos", "30 a 34 anos", "35 a 39 anos",
"40 a 44 anos", "45 a 49 anos", "50 a 54 anos", "55 a 59 anos",
"60 a 64 anos", "65 a 69 anos", "70 a 74 anos", "75 a 79 anos",
"80 a 84 anos", "85 a 89 anos", "90 a 94 anos", "95 a 99 anos",
"100 anos +"
),
populacao = c(
80947, 93275, 89504, 95331, 108788, 110525, 111506, 116312,
118769, 105430, 100962, 93575, 81917, 63441, 47650, 31091,
20825, 11611, 5401, 1722, 338
)
)Desagregação necessária para comparar a cobertura vacinal entre
homens e mulheres dentro de cada grupo de idade, controlando as
diferenças na estrutura demográfica entre os sexos. Os valores
masculinos e femininos são empilhados em formato longo com
rep().
pop_faixa_sexo <- tibble(
faixa_etaria = rep(c(
"0 a 4 anos", "5 a 9 anos", "10 a 14 anos", "15 a 19 anos",
"20 a 24 anos", "25 a 29 anos", "30 a 34 anos", "35 a 39 anos",
"40 a 44 anos", "45 a 49 anos", "50 a 54 anos", "55 a 59 anos",
"60 a 64 anos", "65 a 69 anos", "70 a 74 anos", "75 a 79 anos",
"80 a 84 anos", "85 a 89 anos", "90 a 94 anos", "95 a 99 anos",
"100 anos +"
), 2),
sexo = c(rep("MASCULINO", 21), rep("FEMININO", 21)),
populacao = c(
# Homens
41054, 47652, 45880, 48112, 54323, 53561, 52493, 53675,
54520, 47180, 44633, 40334, 34420, 25302, 17912, 10972,
6558, 3268, 1267, 371, 49,
# Mulheres
39893, 45623, 43624, 47219, 54465, 56964, 59013, 62637,
64249, 58250, 56329, 53241, 47497, 38139, 29738, 20119,
14267, 8343, 4134, 1351, 289
)
)Denominador para o cálculo de cobertura por grupo racial, considerando as cinco categorias do IBGE: Branca, Preta, Amarela, Parda e Indígena. Esses totais correspondem à população recifense declarada no Censo 2022, independentemente da faixa etária.
Desagregação cruzada que permite investigar disparidades raciais de cobertura dentro de cada grupo etário, que é a granularidade mais fina disponível nos dados censitários utilizados. As cinco categorias raciais são empilhadas sobre as 21 faixas etárias, totalizando 105 combinações.
pop_faixa_raca <- tibble(
faixa_etaria = rep(c(
"0 a 4 anos", "5 a 9 anos", "10 a 14 anos", "15 a 19 anos",
"20 a 24 anos", "25 a 29 anos", "30 a 34 anos", "35 a 39 anos",
"40 a 44 anos", "45 a 49 anos", "50 a 54 anos", "55 a 59 anos",
"60 a 64 anos", "65 a 69 anos", "70 a 74 anos", "75 a 79 anos",
"80 a 84 anos", "85 a 89 anos", "90 a 94 anos", "95 a 99 anos",
"100 anos +"
), 5),
raca_cor = c(
rep("BRANCA", 21), rep("PRETA", 21), rep("AMARELA", 21),
rep("PARDA", 21), rep("INDÍGENA", 21)
),
populacao = c(
# BRANCA
35612, 36588, 33389, 34570, 39109, 39916, 41560, 42659,
44815, 38765, 36892, 36017, 32759, 26888, 21848, 15369,
10861, 6445, 3148, 1026, 177,
# PRETA
6109, 8212, 8683, 11698, 14877, 15658, 15207, 15697,
15830, 14304, 14146, 12074, 10411, 7564, 5274, 3113,
1992, 1024, 475, 157, 41,
# AMARELA
102, 138, 120, 172, 215, 238, 231, 261,
237, 177, 180, 172, 139, 110, 81, 59,
38, 21, 8, 4, 0,
# PARDA
39029, 48221, 47183, 48742, 54408, 54522, 54305, 57473,
57650, 51998, 49535, 45102, 38424, 28732, 20329, 12490,
7910, 4089, 1763, 530, 120,
# INDÍGENA
95, 114, 127, 147, 177, 185, 200, 220,
234, 181, 206, 208, 179, 139, 118, 59,
24, 31, 7, 5, 0
)
)Os tibbles populacionais são unidos aos dados de vacinação via
left_join, gerando quatro bases analíticas com a taxa de
cobertura calculada como razão entre doses registradas e população de
referência em cada estrato. Valores acima de 1,0 são esperados em faixas
onde há doses de reforço acumuladas ou migração de vacinados de outros
municípios.
# Doses por faixa etária com cobertura
doses_faixa <- vacina |>
count(faixa_etaria, name = "doses") |>
left_join(pop_faixa, by = "faixa_etaria") |>
mutate(cobertura = doses / populacao)
# Doses por faixa etária e sexo com cobertura
doses_faixa_sexo <- vacina |>
filter(sexo %in% c("MASCULINO", "FEMININO")) |>
count(faixa_etaria, sexo, name = "doses") |>
left_join(pop_faixa_sexo, by = c("faixa_etaria", "sexo")) |>
mutate(cobertura = doses / populacao)
# Doses por raça/cor com cobertura
doses_raca <- vacina |>
filter(!is.na(raca_cor)) |>
count(raca_cor, name = "doses") |>
left_join(pop_raca, by = "raca_cor") |>
mutate(cobertura = doses / populacao)
# Doses por faixa etária e raça/cor com cobertura
doses_faixa_raca <- vacina |>
filter(!is.na(raca_cor), !is.na(faixa_etaria)) |>
count(faixa_etaria, raca_cor, name = "doses") |>
left_join(pop_faixa_raca, by = c("faixa_etaria", "raca_cor")) |>
mutate(cobertura = doses / populacao)Após todas as etapas de limpeza, padronização das variáveis textuais
(como raca_cor e vacina_fabricante), derivação
de novos campos (distrito_cod, mes_vacinacao)
e enriquecimento com os dados populacionais do Censo 2022 (IBGE), o
conjunto analítico final passa a contar com 1.424.360 registros e 16
variáveis.
O período efetivamente coberto pelos dados de análise se estende de janeiro de 2022 a dezembro de 2022.
Para apresentar o conjunto de dados resultante de forma condensada e interativa, a tabela abaixo exibe uma amostra aleatória de 200 registros do dataset completamente tratado.
set.seed(2024)
vacina |> slice_sample(n = 200) |>
DT::datatable(
options = list(
scrollX = TRUE,
scrollY = "550px",
pageLength = 25
)
)A análise exploratória de dados nos permite compreender a dinâmica da campanha de vacinação em Recife em 2022. As subseções a seguir detalham os aspectos temporais, demográficos, logísticos e geográficos das doses aplicadas.
O gráfico de área abaixo ilustra a evolução mensal das doses aplicadas em Recife ao longo de 2022.
evo_mes <- vacina |>
count(mes_vacinacao, name = "doses") |>
filter(!is.na(mes_vacinacao))
p_temporal <- ggplot(evo_mes, aes(x = mes_vacinacao, y = doses)) +
geom_area(fill = "#023e8a", alpha = 0.55) +
geom_line(color = "#0077b6", linewidth = 1.2) +
geom_point(aes(text = paste("Mês:", format(mes_vacinacao, "%B/%y"),
"<br>Doses:", format(doses, big.mark = ".", decimal.mark = ","))),
color = "#03045e", size = 2.5) +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
scale_x_date(date_labels = "%b/%y", date_breaks = "1 month") +
labs(
title = "Evolução Mensal de Doses Aplicadas em Recife (2022)",
x = NULL,
y = "Doses Aplicadas"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 12, color = "#1d3557", margin = margin(b = 10)),
axis.text.x = element_text(angle = 45, hjust = 1),
panel.grid.minor = element_blank()
)
ggplotly(p_temporal, tooltip = "text")O volume de vacinação em Recife atingiu seus patamares mais elevados no primeiro quadrimestre de 2022 (janeiro a abril), com picos em janeiro (mais de 215 mil doses) e março (mais de 222 mil doses), impulsionado pela busca pelo primeiro reforço (3ª dose) e pelo início da campanha infantil em fevereiro. A partir de maio, o ritmo desacelera de forma geral, exibindo um segundo pico intermediário em junho e julho (cerca de 148 mil doses mensais) decorrente da liberação do segundo reforço (4ª dose) para o público adulto geral, seguido de uma queda progressiva no segundo semestre do ano.
O gráfico de colunas abaixo mostra a distribuição acumulada das doses por dia da semana em 2022.
doses_dia <- vacina |>
filter(!is.na(data_vacinacao)) |>
mutate(
dia_num = wday(data_vacinacao, week_start = 1),
dia_semana = case_when(
dia_num == 1 ~ "Segunda-Feira",
dia_num == 2 ~ "Terça-Feira",
dia_num == 3 ~ "Quarta-Feira",
dia_num == 4 ~ "Quinta-Feira",
dia_num == 5 ~ "Sexta-Feira",
dia_num == 6 ~ "Sábado",
dia_num == 7 ~ "Domingo"
) |> factor(levels = c("Segunda-Feira", "Terça-Feira", "Quarta-Feira",
"Quinta-Feira", "Sexta-Feira", "Sábado", "Domingo"))
) |>
count(dia_semana, name = "doses")
p_semanal <- ggplot(doses_dia, aes(x = dia_semana, y = doses, fill = dia_semana)) +
geom_col(alpha = 0.85, show.legend = FALSE) +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
scale_fill_brewer(palette = "Blues") +
labs(
title = "Volume de Vacinação por Dia da Semana em Recife (2022)",
x = NULL,
y = "Doses Aplicadas"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 12, color = "#1d3557", margin = margin(b = 10)),
axis.text.x = element_text(angle = 45, hjust = 1),
panel.grid.minor = element_blank()
)
ggplotly(p_semanal)A distribuição diária revela um ritmo forte e distribuído ao longo de quase toda a semana. Os picos de atividade ocorrem de terça a quinta-feira (liderados pela terça-feira, com mais de 231 mil doses). Destaca-se o volume expressivo registrado aos sábados (mais de 206 mil doses), superando inclusive as segundas-feiras (180 mil doses). Isso indica a relevância do funcionamento e do atendimento ativo aos sábados, viabilizando o acesso para a população que possivelmente encontrava barreiras nos dias úteis, restando apenas o domingo com um volume menor, embora ainda expressivo (140 mil doses).
O gráfico abaixo detalha como o foco das etapas vacinais (esquema primário vs. reforços) se transformou mensalmente.
doses_mes_tipo <- vacina |>
filter(!is.na(mes_vacinacao), !is.na(descricao_dose)) |>
count(mes_vacinacao, descricao_dose, name = "doses")
p_mes_tipo <- ggplot(doses_mes_tipo, aes(x = mes_vacinacao, y = doses, fill = descricao_dose,
text = paste("Mês:", format(mes_vacinacao, "%B/%y"),
"<br>Etapa:", descricao_dose,
"<br>Doses:", format(doses, big.mark = ".", decimal.mark = ",")))) +
geom_col(position = "stack", alpha = 0.85, width = 20) +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
scale_x_date(date_labels = "%b/%y", date_breaks = "1 month") +
scale_fill_brewer(palette = "Blues", direction = -1) +
labs(
title = "Distribuição Mensal de Doses por Etapa Vacinal (2022)",
x = NULL,
y = "Doses Aplicadas",
fill = "Etapa"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 11, color = "#1d3557", margin = margin(b = 10)),
axis.text.x = element_text(angle = 45, hjust = 1),
panel.grid.minor = element_blank(),
legend.position = "bottom"
)
ggplotly(p_mes_tipo, tooltip = "text")A campanha transitou entre diferentes prioridades: * Janeiro-Março: Concentração no primeiro reforço (3ª dose) de adultos e no início da imunização infantil (fevereiro/março). * Abril-Julho: Liberação e pico do segundo reforço (4ª dose) para idosos, adultos e trabalhadores de saúde. * Novembro-Dezembro: Introdução progressiva de doses de terceiro reforço (5ª dose) para públicos de maior vulnerabilidade clínica.
O gráfico abaixo ilustra o volume total de doses aplicadas por grupo etário decenal e sexo em 2022.
doses_faixa_sexo_grouped <- doses_faixa_sexo |>
mutate(
grupo_etario = case_when(
faixa_etaria %in% c("0 a 4 anos", "5 a 9 anos") ~ "0-9 anos",
faixa_etaria %in% c("10 a 14 anos", "15 a 19 anos") ~ "10-19 anos",
faixa_etaria %in% c("20 a 24 anos", "25 a 29 anos") ~ "20-29 anos",
faixa_etaria %in% c("30 a 34 anos", "35 a 39 anos") ~ "30-39 anos",
faixa_etaria %in% c("40 a 44 anos", "45 a 49 anos") ~ "40-49 anos",
faixa_etaria %in% c("50 a 54 anos", "55 a 59 anos") ~ "50-59 anos",
faixa_etaria %in% c("60 a 64 anos", "65 a 69 anos") ~ "60-69 anos",
faixa_etaria %in% c("70 a 74 anos", "75 a 79 anos") ~ "70-79 anos",
TRUE ~ "80+ anos"
) |> factor(levels = c("0-9 anos", "10-19 anos", "20-29 anos", "30-39 anos",
"40-49 anos", "50-59 anos", "60-69 anos", "70-79 anos",
"80+ anos"))
) |>
group_by(grupo_etario, sexo) |>
summarise(doses = sum(doses), .groups = "drop")
p_demog_sexo <- doses_faixa_sexo_grouped |>
filter(!is.na(grupo_etario), !is.na(sexo)) |>
ggplot(aes(x = grupo_etario, y = doses, fill = sexo,
text = paste("Faixa:", grupo_etario,
"<br>Sexo:", sexo,
"<br>Doses:", format(doses, big.mark = ".", decimal.mark = ",")))) +
geom_col(position = "dodge", alpha = 0.85) +
coord_flip() +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
scale_fill_manual(values = c("FEMININO" = "#e63946", "MASCULINO" = "#457b9d")) +
labs(
title = "Volume de Doses por Grupo Etário e Sexo",
x = NULL,
y = "Doses Aplicadas",
fill = "Sexo"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 11, color = "#1d3557", margin = margin(b = 10)),
legend.position = "bottom",
panel.grid.minor = element_blank()
)
ggplotly(p_demog_sexo, tooltip = "text")A vacinação concentrou-se na população ativa (30 a 59 anos) e nos idosos (60+ anos) devido ao calendário de reforços. Na infância, a faixa de 0 a 9 anos registrou forte volume em fevereiro, enquanto a faixa de 0 a 4 anos apresentou menor participação devido à liberação tardia e hesitação vacinal. Em todos os grupos adultos, o volume feminino superou o masculino, padrão histórico de maior engajamento das mulheres em saúde preventiva.
Os gráficos abaixo exibem a distribuição de doses por autodeclaração de raça/cor absoluta e cruzada com sexo.
p_demog_raca <- doses_raca |>
filter(!is.na(raca_cor)) |>
ggplot(aes(x = reorder(raca_cor, doses), y = doses, fill = raca_cor,
text = paste("Raça/Cor:", raca_cor,
"<br>Doses:", format(doses, big.mark = ".", decimal.mark = ",")))) +
geom_col(alpha = 0.85, show.legend = FALSE) +
coord_flip() +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
scale_fill_brewer(palette = "Set2") +
labs(
title = "Volume de Doses por Raça/Cor",
x = NULL,
y = "Doses Aplicadas"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 11, color = "#1d3557", margin = margin(b = 10)),
panel.grid.minor = element_blank()
)
ggplotly(p_demog_raca, tooltip = "text")doses_raca_sexo <- vacina |>
filter(!is.na(raca_cor), sexo %in% c("MASCULINO", "FEMININO")) |>
count(raca_cor, sexo, name = "doses")
p_demog_raca_sexo <- doses_raca_sexo |>
ggplot(aes(x = reorder(raca_cor, doses, sum), y = doses, fill = sexo,
text = paste("Raça/Cor:", raca_cor,
"<br>Sexo:", sexo,
"<br>Doses:", format(doses, big.mark = ".", decimal.mark = ",")))) +
geom_col(position = "dodge", alpha = 0.85) +
coord_flip() +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
scale_fill_manual(values = c("FEMININO" = "#e63946", "MASCULINO" = "#457b9d")) +
labs(
title = "Volume de Doses por Raça/Cor e Sexo",
x = NULL,
y = "Doses Aplicadas",
fill = "Sexo"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 11, color = "#1d3557", margin = margin(b = 10)),
legend.position = "bottom",
panel.grid.minor = element_blank()
)
ggplotly(p_demog_raca_sexo, tooltip = "text")A população autodeclarada parda concentrou a maioria absoluta de vacinas aplicadas em Recife, seguida pelas populações branca e preta, refletindo a demografia geral da cidade. O maior engajamento feminino em ações de imunização se confirma de forma constante e proporcional em todas as categorias étnico-raciais analisadas.
O gráfico abaixo mostra os 10 principais grupos prioritários cadastrados.
doses_grupo <- vacina |>
filter(!is.na(grupo)) |>
count(grupo, name = "doses") |>
slice_max(doses, n = 10, with_ties = FALSE)
p_demog_grupo <- doses_grupo |>
ggplot(aes(x = reorder(grupo, doses), y = doses, fill = grupo,
text = paste("Grupo:", grupo,
"<br>Doses:", format(doses, big.mark = ".", decimal.mark = ",")))) +
geom_col(alpha = 0.85, show.legend = FALSE) +
coord_flip() +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
scale_fill_viridis_d(option = "viridis") +
labs(
title = "Top 10 Grupos Prioritários por Doses Aplicadas",
x = NULL,
y = "Doses Aplicadas"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 11, color = "#1d3557", margin = margin(b = 10)),
panel.grid.minor = element_blank(),
legend.position = "none"
)
ggplotly(p_demog_grupo, tooltip = "text")A população geral e os idosos representam a maioria absoluta do esforço vacinal em 2022. Profissionais de saúde e de educação lideram nas categorias de prioridades ativas pelo Plano Nacional de Operacionalização (PNO).
O esquema vacinal foi analisado em termos de doses aplicadas em 2022 para mapear o direcionamento logístico entre o esquema inicial e os reforços.
doses_dist <- vacina |>
filter(!is.na(descricao_dose)) |>
count(descricao_dose, name = "quantidade") |>
mutate(percent = quantidade / sum(quantidade))
p_dose <- ggplot(doses_dist, aes(x = descricao_dose, y = quantidade, fill = descricao_dose,
text = paste("Etapa:", descricao_dose,
"<br>Quantidade:", format(quantidade, big.mark = ".", decimal.mark = ","),
"<br>Proporção no Ano:", percent(percent, accuracy = 0.1)))) +
geom_col(alpha = 0.85, show.legend = FALSE) +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
scale_fill_brewer(palette = "Blues") +
labs(
title = "Distribuição de Doses por Etapa Vacinal em Recife (2022)",
x = "Etapa da Vacinação",
y = "Doses Aplicadas"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 11, color = "#1d3557", margin = margin(b = 10)),
panel.grid.minor = element_blank()
)
ggplotly(p_dose, tooltip = "text")doses_dist |>
mutate(
`Acumulado (%)` = cumsum(percent)
) |>
transmute(
`Etapa Vacinal` = descricao_dose,
`Doses Aplicadas` = format(quantidade, big.mark = ".", decimal.mark = ","),
`Proporção (%)` = scales::percent(percent, accuracy = 0.1),
`Acumulado (%)` = scales::percent(`Acumulado (%)`, accuracy = 0.1)
) |>
kable(align = "lrcc") |>
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE,
font_size = 13
) |>
row_spec(which(doses_dist$percent == max(doses_dist$percent)), bold = TRUE, background = "#d4edda")| Etapa Vacinal | Doses Aplicadas | Proporção (%) | Acumulado (%) |
|---|---|---|---|
| 1ª Dose | 176.994 | 12.4% | 12.4% |
| 2ª Dose | 210.199 | 14.8% | 27.2% |
| 1º Reforço | 636.085 | 44.7% | 71.8% |
| 2º Reforço | 395.194 | 27.7% | 99.6% |
| 3º Reforço | 5.888 | 0.4% | 100.0% |
A maior parte dos atendimentos foi focada no primeiro reforço (3ª dose, 44,7% do total anual, correspondendo a 636.085 doses) e no segundo reforço (4ª dose, 27,8% do total, correspondendo a 395.194 doses). Juntas, as doses de reforço superaram 72% de todo o esforço vacinal do ano, refletindo a adaptação logística frente às mutações da COVID-19. Os esquemas primários (1ª e 2ª doses) representaram 27,2%, impulsionados pela vacinação do público infantil.
A análise identifica as vacinas que foram utilizadas e a forma como se distribuíram pelas diferentes etapas da campanha em Recife em 2022.
fabricante_dose <- vacina |>
filter(!is.na(vacina_fabricante), !is.na(descricao_dose)) |>
count(vacina_fabricante, descricao_dose, name = "doses")
p_fabricante <- fabricante_dose |>
ggplot(aes(x = reorder(vacina_fabricante, doses, sum), y = doses, fill = descricao_dose,
text = paste("Fabricante:", vacina_fabricante,
"<br>Etapa:", descricao_dose,
"<br>Doses:", format(doses, big.mark = ".", decimal.mark = ",")))) +
geom_col(alpha = 0.85) +
coord_flip() +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
scale_fill_brewer(palette = "Blues", direction = -1) +
labs(
title = "Distribuição de Imunobiológicos por Etapa Vacinal em Recife (2022)",
x = NULL,
y = "Doses Aplicadas",
fill = "Etapa"
) +
theme_minimal(base_size = 10) +
theme(
plot.title = element_text(face = "bold", size = 11, color = "#1d3557", margin = margin(b = 10)),
legend.position = "right",
panel.grid.minor = element_blank()
)
ggplotly(p_fabricante, tooltip = "text")A vacina da Pfizer (adulto) liderou com 423.907 doses aplicadas (principalmente em reforços). Somando as versões infantil (118.495) e baby (2.205), a marca consolidou-se como principal recurso de proteção. A AstraZeneca/Fiocruz (393.032 doses) e a Janssen (335.588 doses) atuaram como importantes reforços adultos. A CoronaVac (Butantan) teve papel central na vacinação de crianças a partir de 3 anos de idade, registrando 151.134 doses (pediátrica e tradicional combinadas).
O mapa interativo colore os distritos proporcionalmente ao volume absoluto de doses aplicadas em 2022.
# Carregar o GeoJSON dos distritos sanitários
distritos_geo <- st_read("distritos-recife.geojson", quiet = TRUE)
# Agregar doses por distrito, incluindo o nome da unidade de saúde
doses_por_distrito <- vacina |>
filter(!is.na(distrito_cod)) |>
count(distrito_cod, unidade, name = "doses") |>
mutate(percent = doses / sum(doses))
# Garantir compatibilidade de tipos para o join
distritos_geo$cdistscodi <- as.integer(distritos_geo$cdistscodi)
doses_por_distrito$distrito_cod <- as.integer(doses_por_distrito$distrito_cod)
# Usar merge() para compatibilidade total com objetos sf
distritos_geo <- merge(distritos_geo, doses_por_distrito,
by.x = "cdistscodi", by.y = "distrito_cod",
all.x = TRUE)
# Paleta de cores
pal <- colorNumeric(palette = "YlOrRd", domain = distritos_geo$doses, na.color = "#cccccc")
# Rótulos interativos com nome do distrito e unidade de saúde
labels <- sprintf(
"<strong>DS %s</strong><br/>Unidade: %s<br/>Doses: %s<br/>Participação: %s",
distritos_geo$cdistscodi,
ifelse(is.na(distritos_geo$unidade), "-", distritos_geo$unidade),
ifelse(is.na(distritos_geo$doses), "sem dados",
format(distritos_geo$doses, big.mark = ".", decimal.mark = ",")),
ifelse(is.na(distritos_geo$percent), "-",
scales::percent(distritos_geo$percent, accuracy = 0.1))
) |> lapply(htmltools::HTML)
# Mapa Leaflet
leaflet(distritos_geo) |>
addProviderTiles(providers$CartoDB.Positron) |>
addPolygons(
fillColor = ~pal(doses),
weight = 2,
opacity = 1,
color = "white",
dashArray = "3",
fillOpacity = 0.7,
highlightOptions = highlightOptions(
weight = 4, color = "#1d3557", dashArray = "",
fillOpacity = 0.85, bringToFront = TRUE
),
label = labels,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "13px", direction = "auto"
)
) |>
addLegend(
pal = pal,
values = ~doses,
opacity = 0.7,
title = "Doses Aplicadas",
position = "bottomright",
labFormat = labelFormat(big.mark = ".", transform = function(x) x)
)O Distrito 6 (Zona Sul, englobando Boa Viagem e Imbiribeira) liderou com 308.174 doses aplicadas (21,0% do total anual). O Distrito 7 (Casa Amarela e Vasco da Gama) registrou a segunda maior participação com 206.890 doses (14,1%). O Distrito 3 registrou a menor participação (6,9%). Policlínicas e maternidades locais concentraram os principais hubs estruturados.
A tabela e o gráfico a seguir contrastam o percentual de residentes de cada distrito com a proporção de doses aplicadas em 2022.
pop_distritos <- tibble(
distrito_cod = 1:8,
distrito_nome = paste("Distrito", 1:8),
populacao = c(55318, 244686, 94619, 315225, 233153, 244453, 172937, 128529),
bairros = c(
"Recife, Santo Amaro, Boa Vista, Cabanga, Ilha do Leite, Paissandu, Santo Antônio, São José, Coelhos, Soledade, Ilha Joana Bezerra",
"Alto Santa Terezinha, Água Fria, Arruda, Beberibe, Bomba do Hemetério, Campo Grande, Cajueiro, Campina do Barreto, Dois Unidos, Encruzilhada, Fundão, Hipódromo, Linha do Tiro, Ponto de Parada, Porto da Madeira, Peixinhos, Rosarinho, Torreão",
"Aflitos, Alto do Mandu, Apipucos, Casa Amarela, Casa Forte, Derby, Dois Irmãos, Espinheiro, Graças, Jaqueira, Monteiro, Parnamirim, Poço (Poço da Panela), Santana, Sítio dos Pintos, Tamarineira",
"Caxangá, Cidade Universitária, Cordeiro, Engenho do Meio, Ilha do Retiro, Iputinga, Madalena, Prado, Torre, Torrões, Várzea, Zumbi",
"Afogados, Areias, Barro, Bongi, Caçote, Coqueiral, Curado, Estância, Jardim São Paulo, Jiquiá, Mangueira, Mustardinha, Sancho, San Martin, Tejipió, Totó",
"Boa Viagem, Brasília Teimosa, Imbiribeira, Ipsep, Pina",
"Alto José Bonifácio, Alto José do Pinho, Brejo do Guabiraba, Brejo do Beberibe, Córrego do Jenipapo, Guabiraba, Macaxeira, Mangabeira, Morro da Conceição, Nova Descoberta, Passarinho, Pau Ferro, Vasco da Gama",
"Cohab, Ibura, Jordão"
)
)
doses_distrito <- vacina |>
filter(!is.na(distrito_cod)) |>
count(distrito_cod, name = "doses")
comp_distritos <- pop_distritos |>
left_join(doses_distrito, by = "distrito_cod") |>
mutate(
pct_pop = populacao / sum(populacao),
pct_doses = doses / sum(doses),
diferenca = pct_doses - pct_pop
)
comp_distritos_sorted <- comp_distritos |> arrange(distrito_cod)
cores_diff <- ifelse(comp_distritos_sorted$diferenca >= 0, "#27ae60", "#d9534f")
comp_distritos_sorted |>
transmute(
Distrito = distrito_nome,
`Bairros Integrantes` = bairros,
`População (Censo 2022)` = format(populacao, big.mark = ".", decimal.mark = ","),
`Participação na População` = scales::percent(pct_pop, accuracy = 0.01),
`Doses Aplicadas` = format(doses, big.mark = ".", decimal.mark = ","),
`Participação nas Doses` = scales::percent(pct_doses, accuracy = 0.01),
`Diferença (pp)` = scales::percent(diferenca, accuracy = 0.01)
) |>
kable(align = "llrccrc") |>
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = TRUE,
font_size = 12
) |>
column_spec(1, bold = TRUE) |>
column_spec(7, color = "white", background = cores_diff, bold = TRUE)| Distrito | Bairros Integrantes | População (Censo 2022) | Participação na População | Doses Aplicadas | Participação nas Doses | Diferença (pp) |
|---|---|---|---|---|---|---|
| Distrito 1 | Recife, Santo Amaro, Boa Vista, Cabanga, Ilha do Leite, Paissandu, Santo Antônio, São José, Coelhos, Soledade, Ilha Joana Bezerra | 55.318 | 3.72% | 164.613 | 11.56% | 7.84% |
| Distrito 2 | Alto Santa Terezinha, Água Fria, Arruda, Beberibe, Bomba do Hemetério, Campo Grande, Cajueiro, Campina do Barreto, Dois Unidos, Encruzilhada, Fundão, Hipódromo, Linha do Tiro, Ponto de Parada, Porto da Madeira, Peixinhos, Rosarinho, Torreão | 244.686 | 16.43% | 168.040 | 11.80% | -4.64% |
| Distrito 3 | Aflitos, Alto do Mandu, Apipucos, Casa Amarela, Casa Forte, Derby, Dois Irmãos, Espinheiro, Graças, Jaqueira, Monteiro, Parnamirim, Poço (Poço da Panela), Santana, Sítio dos Pintos, Tamarineira | 94.619 | 6.35% | 100.730 | 7.07% | 0.72% |
| Distrito 4 | Caxangá, Cidade Universitária, Cordeiro, Engenho do Meio, Ilha do Retiro, Iputinga, Madalena, Prado, Torre, Torrões, Várzea, Zumbi | 315.225 | 21.17% | 182.612 | 12.82% | -8.35% |
| Distrito 5 | Afogados, Areias, Barro, Bongi, Caçote, Coqueiral, Curado, Estância, Jardim São Paulo, Jiquiá, Mangueira, Mustardinha, Sancho, San Martin, Tejipió, Totó | 233.153 | 15.66% | 148.136 | 10.40% | -5.26% |
| Distrito 6 | Boa Viagem, Brasília Teimosa, Imbiribeira, Ipsep, Pina | 244.453 | 16.42% | 308.173 | 21.64% | 5.22% |
| Distrito 7 | Alto José Bonifácio, Alto José do Pinho, Brejo do Guabiraba, Brejo do Beberibe, Córrego do Jenipapo, Guabiraba, Macaxeira, Mangabeira, Morro da Conceição, Nova Descoberta, Passarinho, Pau Ferro, Vasco da Gama | 172.937 | 11.61% | 206.890 | 14.53% | 2.91% |
| Distrito 8 | Cohab, Ibura, Jordão | 128.529 | 8.63% | 145.166 | 10.19% | 1.56% |
comp_long <- comp_distritos |>
select(distrito_nome, pct_pop, pct_doses) |>
pivot_longer(cols = c(pct_pop, pct_doses), names_to = "metrica", values_to = "percentual") |>
mutate(metrica = case_when(
metrica == "pct_pop" ~ "Participação na População",
metrica == "pct_doses" ~ "Participação nas Doses"
))
p_comp <- ggplot(comp_long, aes(x = reorder(distrito_nome, percentual), y = percentual, fill = metrica,
text = paste("Distrito:", distrito_nome,
"<br>Métrica:", metrica,
"<br>Proporção:", scales::percent(percentual, accuracy = 0.01)))) +
geom_col(position = "dodge", alpha = 0.85) +
coord_flip() +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(values = c("Participação na População" = "#457b9d", "Participação nas Doses" = "#e63946")) +
labs(
title = "Comparação: Participação na População vs. Participação nas Doses por Distrito",
x = NULL,
y = "Proporção",
fill = "Métrica"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 11, color = "#1d3557", margin = margin(b = 10)),
legend.position = "bottom",
panel.grid.minor = element_blank()
)
ggplotly(p_comp, tooltip = "text")A análise comparativa espacial aponta diferenças entre a participação populacional residente de cada distrito e a proporção de doses aplicadas em seus respectivos territórios: * Distrito 1 e Distrito 6: Apresentaram proporções de doses aplicadas superiores à sua participação na população residente (diferenças de +7,84 pp e +5,22 pp, respectivamente). * Distrito 4: Registrou a maior diferença proporcional negativa, representando 21,17% da população residente, mas respondendo por 12,82% das doses aplicadas no território (diferença de -8,35 pp). * Distritos 2 e 5: Apresentaram participações vacinais inferiores às suas participações demográficas residentes (diferenças de -4,64 pp e -5,26 pp, respectivamente).
Essas diferenças indicam descompassos entre o contingente populacional residente e o volume de doses administradas localmente em cada área, refletindo assimetrias na distribuição espacial da aplicação de doses.
O gráfico abaixo exibe a proporção étnico-racial declarada entre os vacinados em cada território em 2022.
doses_raca_distrito <- vacina |>
filter(!is.na(distrito_cod), !is.na(raca_cor)) |>
count(distrito_cod, raca_cor, name = "doses") |>
mutate(distrito_nome = paste("Distrito", distrito_cod))
p_raca_distrito <- doses_raca_distrito |>
ggplot(aes(x = reorder(distrito_nome, doses, sum), y = doses, fill = raca_cor,
text = paste("Distrito:", distrito_nome,
"<br>Raça/Cor:", raca_cor,
"<br>Proporção:", scales::percent(doses / sum(doses), accuracy = 0.1)))) +
geom_col(position = "fill", alpha = 0.85) +
coord_flip() +
scale_y_continuous(labels = scales::percent) +
scale_fill_brewer(palette = "Set2") +
labs(
title = "Distribuição Proporcional de Raça/Cor por Distrito Sanitário (2022)",
x = NULL,
y = "Proporção das Doses",
fill = "Raça/Cor"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 11, color = "#1d3557", margin = margin(b = 10)),
legend.position = "bottom",
panel.grid.minor = element_blank()
)
ggplotly(p_raca_distrito, tooltip = "text")A população autodeclarada parda predomina em todos os distritos. As áreas periféricas e populares (como Distrito 8 e Distrito 2) exibem maior participação de vacinados pardos e pretos. Em contrapartida, distritos de maior renda média (como Distrito 6 e Distrito 3) exibem proporção visivelmente superior de população branca, acompanhando as composições de renda e demografia espacial do Recife.
O gráfico de linhas abaixo mostra a evolução mensal de primeiras doses por distrito e o gráfico de colunas detalha o percentual de reforços aplicados.
primeira_dose_ds <- vacina |>
filter(descricao_dose == "1ª Dose", !is.na(mes_vacinacao), !is.na(distrito_cod)) |>
count(mes_vacinacao, distrito_cod, name = "doses") |>
mutate(distrito_nome = paste("Distrito", distrito_cod)) |>
arrange(mes_vacinacao, distrito_cod)
p_primeira_ds <- ggplot(primeira_dose_ds, aes(x = mes_vacinacao, y = doses, color = distrito_nome, group = distrito_nome,
text = paste("Mês:", format(mes_vacinacao, "%B/%y"),
"<br>Distrito:", distrito_nome,
"<br>Doses:", format(doses, big.mark = ".", decimal.mark = ",")))) +
geom_line(linewidth = 1.0) +
geom_point(size = 1.5) +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
scale_x_date(date_labels = "%b/%y", date_breaks = "1 month") +
scale_color_brewer(palette = "Set1") +
labs(
title = "Evolução Mensal de Primeiras Doses por Distrito Sanitário (2022)",
x = NULL,
y = "Primeiras Doses Aplicadas",
color = "Distrito Sanitário"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 11, color = "#1d3557", margin = margin(b = 10)),
axis.text.x = element_text(angle = 45, hjust = 1),
panel.grid.minor = element_blank(),
legend.position = "bottom"
)
ggplotly(p_primeira_ds, tooltip = "text")adesao_reforco <- vacina |>
filter(!is.na(distrito_cod), !is.na(descricao_dose)) |>
mutate(tipo_dose = case_when(
descricao_dose %in% c("1ª Dose", "2ª Dose") ~ "Esquema Inicial",
TRUE ~ "Reforço"
)) |>
count(distrito_cod, tipo_dose, name = "doses") |>
group_by(distrito_cod) |>
mutate(pct = doses / sum(doses)) |>
ungroup() |>
mutate(distrito_nome = paste("Distrito", distrito_cod))
p_adesao_reforco <- ggplot(adesao_reforco, aes(x = reorder(distrito_nome, pct, function(x) x[2]), y = pct, fill = tipo_dose,
text = paste("Distrito:", distrito_nome,
"<br>Tipo de Dose:", tipo_dose,
"<br>Doses:", format(doses, big.mark = ".", decimal.mark = ","),
"<br>Proporção:", scales::percent(pct, accuracy = 0.1)))) +
geom_col(position = "fill", alpha = 0.85) +
coord_flip() +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(values = c("Esquema Inicial" = "#a8dadc", "Reforço" = "#457b9d")) +
labs(
title = "Proporção de Doses de Esquema Inicial vs. Reforço por Distrito Sanitário",
x = NULL,
y = "Proporção de Doses",
fill = "Tipo de Dose"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 11, color = "#1d3557", margin = margin(b = 10)),
legend.position = "bottom",
panel.grid.minor = element_blank()
)
ggplotly(p_adesao_reforco, tooltip = "text")A evolução de 1ª dose mostra um pico em fevereiro (abertura infantil), liderado pelo Distrito 8 (16.204 doses) e Distrito 4 (15.773 doses), com posterior queda a patamares residuais. Os distritos das zonas central e sul (Distrito 6 lidera com 84,8% de reforços, seguido pelo Distrito 3 com 80,4% e Distrito 7 com 79,8%) exibem maior maturidade vacinal. Por outro lado, distritos periféricos (Distrito 8 e Distrito 4) concentraram cerca de 40% das doses aplicadas no esquema inicial em 2022, indicando barreiras de acesso prévias, maior necessidade de busca ativa ou demografia de menor faixa etária.
A cronologia mostra como a faixa etária dos vacinados moldou o fluxo da campanha em 2022 por meio das tendências de aplicação de doses por faixa.
p_linhas <- cruzado_df |>
ggplot(aes(x = mes_vacinacao, y = doses, color = grupo_etario, group = grupo_etario,
text = paste("Mês:", format(mes_vacinacao, "%B/%y"),
"<br>Grupo:", grupo_etario,
"<br>Doses:", format(doses, big.mark = ".", decimal.mark = ",")))) +
geom_line(linewidth = 1.2) +
geom_point(size = 2) +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
scale_x_date(date_labels = "%b/%y", date_breaks = "1 month") +
scale_color_brewer(palette = "Set1") +
labs(
title = "Evolução Mensal de Vacinação por Grupo Etário (2022)",
x = NULL,
y = "Doses Aplicadas",
color = "Grupo Etário"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 12, color = "#1d3557", margin = margin(b = 10)),
axis.text.x = element_text(angle = 45, hjust = 1),
panel.grid.minor = element_blank(),
legend.position = "bottom"
)
ggplotly(p_linhas, tooltip = "text")O cruzamento das variáveis ilustra o calendário municipal: * Janeiro: Busca acelerada de adultos (20-59 anos) pelo primeiro reforço (3ª dose) frente à Ômicron. * Fevereiro: Entrada massiva de crianças de 0 a 11 anos no início da campanha infantil (65 mil doses, 34,6% do mês). * Abril: Pico de idosos (60+ anos) motivado pela liberação do segundo reforço (4ª dose) para a terceira idade (84.165 doses). * Junho-Julho: Ampliação do segundo reforço para faixas de adultos jovens, provocando nova elevação na curva de adultos.
O gráfico e a tabela a seguir mostram o número médio de doses aplicadas por habitante em cada faixa etária (razão entre o total de doses aplicadas no ano e a população residente do Censo 2022). Esta métrica ilustra a intensidade vacinal e a adesão da campanha. Como os cidadãos receberam múltiplas doses ao longo do ano, os valores para adultos e idosos naturalmente ultrapassam 1,0 (ou 100% de doses/habitante).
p_doses_capita <- doses_faixa |>
filter(!is.na(faixa_etaria)) |>
mutate(faixa_etaria = factor(faixa_etaria, levels = pop_faixa$faixa_etaria)) |>
ggplot(aes(x = faixa_etaria, y = cobertura, fill = cobertura,
text = paste("Faixa Etária:", faixa_etaria,
"<br>Doses por Habitante:", round(cobertura, 2),
"<br>Total de Doses:", format(doses, big.mark = ".", decimal.mark = ","),
"<br>População:", format(populacao, big.mark = ".", decimal.mark = ",")))) +
geom_col(alpha = 0.85) +
scale_y_continuous(labels = label_number(decimal.mark = ",")) +
scale_fill_viridis_c(option = "mako", direction = -1) +
labs(
title = "Número Médio de Doses Aplicadas por Habitante por Faixa Etária (2022)",
x = "Faixa Etária",
y = "Doses por Habitante",
fill = "Doses/Hab"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 11, color = "#1d3557", margin = margin(b = 10)),
axis.text.x = element_text(angle = 45, hjust = 1),
panel.grid.minor = element_blank(),
legend.position = "none"
)
ggplotly(p_doses_capita, tooltip = "text")doses_faixa |>
filter(!is.na(faixa_etaria)) |>
mutate(faixa_etaria = factor(faixa_etaria, levels = pop_faixa$faixa_etaria)) |>
arrange(faixa_etaria) |>
transmute(
`Faixa Etária` = faixa_etaria,
`Doses Aplicadas` = format(doses, big.mark = ".", decimal.mark = ","),
`População (Censo 2022)` = format(populacao, big.mark = ".", decimal.mark = ","),
`Doses por Habitante` = round(cobertura, 2)
) |>
kable(align = "lrrc") |>
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE,
font_size = 13
) |>
column_spec(1, bold = TRUE)| Faixa Etária | Doses Aplicadas | População (Censo 2022) | Doses por Habitante |
|---|---|---|---|
| 0 a 4 anos | 17.295 | 80.947 | 0.21 |
| 5 a 9 anos | 141.066 | 93.275 | 1.51 |
| 10 a 14 anos | 104.212 | 89.504 | 1.16 |
| 15 a 19 anos | 71.674 | 95.331 | 0.75 |
| 20 a 24 anos | 92.710 | 108.788 | 0.85 |
| 25 a 29 anos | 95.573 | 110.525 | 0.86 |
| 30 a 34 anos | 93.496 | 111.506 | 0.84 |
| 35 a 39 anos | 96.556 | 116.312 | 0.83 |
| 40 a 44 anos | 127.932 | 118.769 | 1.08 |
| 45 a 49 anos | 116.246 | 105.430 | 1.10 |
| 50 a 54 anos | 108.837 | 100.962 | 1.08 |
| 55 a 59 anos | 105.470 | 93.575 | 1.13 |
| 60 a 64 anos | 81.593 | 81.917 | 1.00 |
| 65 a 69 anos | 59.717 | 63.441 | 0.94 |
| 70 a 74 anos | 42.034 | 47.650 | 0.88 |
| 75 a 79 anos | 27.302 | 31.091 | 0.88 |
| 80 a 84 anos | 22.719 | 20.825 | 1.09 |
| 85 a 89 anos | 12.428 | 11.611 | 1.07 |
| 90 a 94 anos | 5.546 | 5.401 | 1.03 |
| 95 a 99 anos | 1.621 | 1.722 | 0.94 |
| 100 anos + | 331 | 338 | 0.98 |
O volume médio de doses por habitante supera 1,0 em diversas faixas adultas e idosas devido às doses múltiplas de reforço aplicadas ao mesmo residente em 2022. As faixas infantis (especialmente de 0 a 4 anos) exibem taxas menores, enfatizando a necessidade de reforço em campanhas escolares de busca ativa.
A tabela e o gráfico abaixo avaliam a equidade na cobertura vacinal comparada ao Censo 2022 e a maturidade vacinal por raça/cor (esquema básico vs. reforços).
# Tabela IBGE vs doses (já declarada no Rmd, podemos usar a mesma estrutura ou uma cópia local)
doses_raca |>
filter(!is.na(raca_cor)) |>
mutate(
pct_doses = doses / sum(doses),
pct_pop = populacao / sum(populacao)
) |>
arrange(desc(doses)) |>
transmute(
`Raça/Cor` = raca_cor,
`Doses Aplicadas` = format(doses, big.mark = ".", decimal.mark = ","),
`Participação nas Doses` = scales::percent(pct_doses, accuracy = 0.1),
`População (Censo 2022)` = format(populacao, big.mark = ".", decimal.mark = ","),
`Participação na População` = scales::percent(pct_pop, accuracy = 0.1)
) |>
kable(align = "lrrcc") |>
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE,
font_size = 13
) |>
column_spec(1, bold = TRUE)| Raça/Cor | Doses Aplicadas | Participação nas Doses | População (Censo 2022) | Participação na População |
|---|---|---|---|---|
| PARDA | 677.077 | 47.8% | 722.555 | 48.5% |
| BRANCA | 518.131 | 36.6% | 578.413 | 38.8% |
| PRETA | 167.923 | 11.9% | 182.546 | 12.3% |
| AMARELA | 48.312 | 3.4% | 2.703 | 0.2% |
| INDÍGENA | 4.235 | 0.3% | 2.656 | 0.2% |
doses_raca_tipo <- vacina |>
filter(!is.na(raca_cor), !is.na(descricao_dose)) |>
mutate(tipo_dose = if_else(
descricao_dose %in% c("1ª Dose", "2ª Dose"),
"Esquema Inicial",
"Dose de Reforço"
)) |>
count(raca_cor, tipo_dose, name = "doses") |>
group_by(raca_cor) |>
mutate(
total = sum(doses),
percentual = doses / total
) |>
ungroup()
p_raca_tipo <- ggplot(doses_raca_tipo, aes(x = raca_cor, y = percentual, fill = tipo_dose,
text = paste("Raça/Cor:", raca_cor,
"<br>Tipo de Dose:", tipo_dose,
"<br>Qtd Doses:", format(doses, big.mark = ".", decimal.mark = ","),
"<br>Proporção:", scales::percent(percentual, accuracy = 0.1)))) +
geom_col(position = "fill", alpha = 0.85) +
scale_y_continuous(labels = scales::percent_format()) +
scale_fill_manual(values = c("Esquema Inicial" = "#457b9d", "Dose de Reforço" = "#e63946")) +
labs(
title = "Proporção de Doses Iniciais vs. Doses de Reforço por Raça/Cor em Recife (2022)",
x = "Raça/Cor",
y = "Proporção de Doses",
fill = "Tipo de Dose"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 11, color = "#1d3557", margin = margin(b = 10)),
legend.position = "bottom",
panel.grid.minor = element_blank()
)
ggplotly(p_raca_tipo, tooltip = "text")doses_raca_tipo |>
select(raca_cor, tipo_dose, doses) |>
pivot_wider(names_from = tipo_dose, values_from = doses) |>
mutate(
Total = `Esquema Inicial` + `Dose de Reforço`,
`% Esquema Inicial` = `Esquema Inicial` / Total,
`% Dose de Reforço` = `Dose de Reforço` / Total
) |>
arrange(desc(Total)) |>
transmute(
`Raça/Cor` = raca_cor,
`Esquema Inicial (Qtd)` = format(`Esquema Inicial`, big.mark = ".", decimal.mark = ","),
`Esquema Inicial (%)` = scales::percent(`% Esquema Inicial`, accuracy = 0.1),
`Dose de Reforço (Qtd)` = format(`Dose de Reforço`, big.mark = ".", decimal.mark = ","),
`Dose de Reforço (%)` = scales::percent(`% Dose de Reforço`, accuracy = 0.1),
`Total de Doses` = format(Total, big.mark = ".", decimal.mark = ",")
) |>
kable(align = "lrrrrr") |>
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE,
font_size = 13
) |>
column_spec(1, bold = TRUE)| Raça/Cor | Esquema Inicial (Qtd) | Esquema Inicial (%) | Dose de Reforço (Qtd) | Dose de Reforço (%) | Total de Doses |
|---|---|---|---|---|---|
| PARDA | 201.151 | 29.7% | 475.926 | 70.3% | 677.077 |
| BRANCA | 121.074 | 23.4% | 397.057 | 76.6% | 518.131 |
| PRETA | 39.628 | 23.6% | 128.295 | 76.4% | 167.923 |
| AMARELA | 22.927 | 47.5% | 25.385 | 52.5% | 48.312 |
| INDÍGENA | 1.318 | 31.1% | 2.917 | 68.9% | 4.235 |
A participação de pardos (49,2%) e brancos (38,1%) reflete de perto suas participações demográficas reais, indicando equidade no acesso geral no território. Em relação à composição das doses aplicadas no ano, as populações branca e preta exibiram maior proporção de doses de reforço (76,6% e 76,4% respectivamente). Em contrapartida, as populações parda e indígena registraram proporções de doses iniciais em torno de 29,7% e 31,1%. Essas diferenças na distribuição dos tipos de dose podem estar associadas a variações na estrutura etária de cada grupo populacional, com maior peso de crianças e jovens em certas populações (que iniciaram seus esquemas em 2022), ou a dinâmicas específicas de busca pelas etapas da campanha. O grupo amarelo (47,5% inicial) destaca-se pelo viés de preenchimento nos cadastros infantis.
O gráfico abaixo exibe o percentual de vacinação de cada sexo por etapa do calendário vacinal, evidenciando o fenômeno de fadiga vacinal.
fatiga_genero <- vacina |>
filter(sexo %in% c("MASCULINO", "FEMININO"), !is.na(descricao_dose)) |>
count(descricao_dose, sexo, name = "doses") |>
group_by(descricao_dose) |>
mutate(pct = doses / sum(doses)) |>
ungroup()
p_fatiga <- ggplot(fatiga_genero, aes(x = descricao_dose, y = pct, fill = sexo,
text = paste("Etapa:", descricao_dose,
"<br>Sexo:", sexo,
"<br>Doses:", format(doses, big.mark = ".", decimal.mark = ","),
"<br>Proporção:", scales::percent(pct, accuracy = 0.1)))) +
geom_col(position = "dodge", alpha = 0.85) +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(values = c("FEMININO" = "#e63946", "MASCULINO" = "#457b9d")) +
labs(
title = "Fadiga Vacinal: Proporção de Aplicações por Sexo e Etapa Vacinal",
x = "Etapa Vacinal",
y = "Proporção de Doses",
fill = "Sexo"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 11, color = "#1d3557", margin = margin(b = 10)),
legend.position = "bottom",
panel.grid.minor = element_blank()
)
ggplotly(p_fatiga, tooltip = "text")Nas duas doses iniciais infantis e de adolescentes de 2022, a participação foi equilibrada entre os sexos. Todavia, à medida que avançamos para as doses de reforço voluntárias em adultos, a participação masculina cai de forma drástica: homens caem de 50,4% nas doses de esquema básico para apenas 37,6% no segundo reforço (4ª dose) e 31,7% no terceiro reforço (5ª dose), ilustrando forte fadiga vacinal ou menor adesão ativa do público masculino aos reforços.
A análise da vacinação contra a COVID-19 em Recife no ano de 2022 mostra que a cidade atingiu um patamar avançado na campanha, com mais de 72% das doses aplicadas destinadas ao reforço. Embora os dados indiquem um acesso equilibrado por raça e cor, o que aponta para o bom funcionamento dos postos e do sistema de agendamento, a análise detalhada revela diferenças na adesão que ainda exigem atenção.
Uma das diferenças mais marcantes ocorre entre homens e mulheres. Enquanto a vacinação inicial é equilibrada, há uma queda na participação dos homens nas doses de reforço. Esse menor interesse masculino contrasta com a maior presença das mulheres nas ações de prevenção. O fator socioeconômico também influenciou a busca pelas doses extras: os distritos sanitários 3 e 6, que abrangem bairros de maior renda, registraram índices de reforço acima da média das outras regiões. Por fim, na divisão por idade, a maior dificuldade está na faixa de 0 a 4 anos, cujo baixo número de vacinados contrasta com os bons resultados obtidos na faixa de 5 a 9 anos, refletindo a liberação tardia das vacinas infantis e a hesitação de pais e responsáveis.
A partir desses resultados, surgem caminhos práticos para melhorar as ações de saúde na cidade. Para vacinar mais crianças de até 4 anos, o agendamento pela internet não é suficiente. É preciso levar as vacinas diretamente a creches e escolas, além de incentivar a recomendação médica nas consultas de rotina dos postos de saúde. Da mesma forma, para combater o desinteresse dos homens adultos pelas doses extras, recomenda-se criar campanhas de comunicação voltadas a esse público, esclarecendo que a proteção inicial diminui com o tempo. Na parte operacional, alguns erros identificados no registro de raça e cor nos cadastros mostram a necessidade de treinar as equipes de atendimento para garantir a anotação correta dessas informações, que são essenciais para planejar as ações de saúde.
Por fim, é importante considerar as limitações desta análise. Ter dados apenas de 2022 impede uma visão completa de todo o cenário, pois deixa de fora o início da vacinação em 2021 e o período de transição em 2023. Além disso, a análise depende de registros que podem conter atrasos ou falhas de preenchimento. Outro ponto é que Recife atrai moradores de cidades vizinhas para seus postos de saúde, o que pode elevar os números calculados para os moradores locais. Como continuidade, recomenda-se analisar os dados de todos os anos da campanha e cruzar essas informações com o banco de dados de internações por gripe (SIVEP-Gripe). Esse cruzamento permitirá avaliar se as regiões com maior cobertura vacinal tiveram menos internações e mortes por COVID-19, ajudando a planejar melhor as próximas campanhas.
## R version 4.5.3 (2026-03-11 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## locale:
## [1] LC_COLLATE=Portuguese_Brazil.utf8 LC_CTYPE=Portuguese_Brazil.utf8
## [3] LC_MONETARY=Portuguese_Brazil.utf8 LC_NUMERIC=C
## [5] LC_TIME=Portuguese_Brazil.utf8
##
## time zone: America/Sao_Paulo
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] leaflet_2.2.3 sf_1.1-1 kableExtra_1.4.0 knitr_1.51
## [5] DT_0.34.0 scales_1.4.0 plotly_4.12.0 lubridate_1.9.5
## [9] forcats_1.0.1 stringr_1.6.0 dplyr_1.2.0 purrr_1.2.2
## [13] readr_2.2.0 tidyr_1.3.2 tibble_3.3.1 ggplot2_4.0.3
## [17] tidyverse_2.0.0
##
## loaded via a namespace (and not attached):
## [1] gtable_0.3.6 xfun_0.57 bslib_0.11.0
## [4] htmlwidgets_1.6.4 tzdb_0.5.0 leaflet.providers_3.0.0
## [7] vctrs_0.7.2 tools_4.5.3 crosstalk_1.2.2
## [10] generics_0.1.4 parallel_4.5.3 proxy_0.4-29
## [13] pkgconfig_2.0.3 KernSmooth_2.23-26 data.table_1.18.2.1
## [16] RColorBrewer_1.1-3 S7_0.2.1 lifecycle_1.0.5
## [19] compiler_4.5.3 farver_2.1.2 textshaping_1.0.5
## [22] htmltools_0.5.9 class_7.3-23 sass_0.4.10
## [25] yaml_2.3.12 lazyeval_0.2.3 crayon_1.5.3
## [28] pillar_1.11.1 jquerylib_0.1.4 classInt_0.4-11
## [31] cachem_1.1.0 tidyselect_1.2.1 digest_0.6.39
## [34] stringi_1.8.7 labeling_0.4.3 fastmap_1.2.0
## [37] grid_4.5.3 cli_3.6.5 magrittr_2.0.4
## [40] e1071_1.7-17 withr_3.0.2 bit64_4.6.0-1
## [43] timechange_0.4.0 rmarkdown_2.31 httr_1.4.8
## [46] bit_4.6.0 otel_0.2.0 hms_1.1.4
## [49] evaluate_1.0.5 viridisLite_0.4.3 rlang_1.1.7
## [52] Rcpp_1.1.1-1.1 glue_1.8.0 DBI_1.3.0
## [55] xml2_1.5.2 svglite_2.2.2 rstudioapi_0.18.0
## [58] vroom_1.7.1 jsonlite_2.0.0 R6_2.6.1
## [61] systemfonts_1.3.2 units_1.0-1