A vacinação contra a COVID-19 foi 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, acumulando mais de um milhão de doses aplicadas entre esquemas primários e reforços. Compreender o perfil dessa campanha, incluindo quem foi vacinado, quando, com qual imunobiológico e em qual região da cidade, é fundamental para extrair lições que orientem futuras ações de imunização em larga escala.
Este projeto realiza uma análise exploratória dos dados abertos de vacinação contra COVID-19 em Recife, disponibilizados pela Prefeitura no portal de dados abertos. O tratamento dos dados envolveu padronização de variáveis categóricas, conversão de datas, separação de campos compostos e criação de variáveis derivadas, como contagem de doses por grupo e agregação mensal. Para contextualizar os volumes de doses aplicadas, os registros foram cruzados com estimativas populacionais do Censo Demográfico 2022 do IBGE, permitindo o cálculo de taxas de cobertura por faixa etária, sexo e raça/cor.
A análise exploratória busca revelar padrões na distribuição temporal, demográfica e geográfica da vacinação, identificando comportamentos que não seriam evidentes nos números agregados, como variações no ritmo de aplicação ao longo dos meses, diferenças de cobertura entre grupos populacionais e a concentração espacial das doses nos distritos sanitários.
Os resultados oferecem uma visão detalhada de como a campanha se desenvolveu no território recifense. As análises aqui apresentadas podem servir de referência para a avaliação de futuras ações de imunização em larga escala, bem como para a identificação de pontos de atenção que mereçam acompanhamento em campanhas subsequentes.
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). |
| janitor | Limpeza de dados, padronização de colunas e tabelas de frequência (não ativo). |
| 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. |
| skimr | Criação de resumos estatísticos rápidos da estrutura dos dados (não ativo). |
| 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,
incluindo informações demográficas do vacinado (idade, sexo, raça/cor,
faixa etária), dados da aplicação (data, dose, fabricante do
imunobiológico), grupo prioritário, categoria de atendimento e
localização da unidade de saúde (codificada em uma coluna
cnes que combina o distrito sanitário e o nome da
unidade).
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 é recodificada de valores
inteiros (1 a 6) para um fator ordenado com rótulos descritivos
("1ª Dose", "2ª Dose",
"1º Reforço", e assim por diante). 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 transformações, o conjunto conta com 1424361 registros e 16 variáveis.
## Rows: 1,424,361
## Columns: 16
## $ 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, 45, 37, 44, 43, 35, …
## $ 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> "COMIRNATY (PFIZER)", "COMIRNATY (PFIZER)", "COMIRNA…
## $ descricao_dose <fct> 1º Reforço, 1º Reforço, 1º Reforço, 1º Reforço, 1º R…
## $ sistema_origem <chr> "Conecta Recife", "Conecta Recife", "Conecta Recife"…
## $ data_vacinacao <date> 2022-01-24, 2022-01-11, 2022-01-08, 2022-02-18, 202…
## $ distrito <chr> "DS 1", "DS 5", "DS 5", "DS 2", "DS 7", "DS 6", "DS …
## $ unidade <chr> "POLICLÍNICA GOUVEIA DE BARROS", "MATERNIDADE BANDEI…
## $ mes_vacinacao <date> 2022-01-01, 2022-01-01, 2022-01-01, 2022-02-01, 202…
## $ distrito_cod <int> 1, 5, 5, 2, 7, 6, 8, 5, 1, 8, 1, 8, 6, 5, 3, 7, 4, 8…
A tabela a seguir apresenta um resumo consolidado de todas as variáveis do dataset limpo, incluindo o tipo de dado, a quantidade de valores únicos, a proporção de valores ausentes e um exemplo de valor observado.
# Tabela resumida das variáveis do dataset limpo
resumo_vars <- tibble(
Variável = names(vacina),
Tipo = sapply(vacina, \(x) class(x)[1]),
`Valores Únicos` = sapply(vacina, n_distinct),
`NAs (%)` = sapply(vacina, \(x) scales::percent(mean(is.na(x)), accuracy = 0.01)),
`Exemplo` = sapply(vacina, \(x) {
val <- na.omit(x)[1]
if (is.null(val) || length(val) == 0) return("—")
as.character(val)
})
)
resumo_vars |>
kable(align = "llccl", caption = "Resumo Consolidado das Variáveis do Dataset Limpo") |>
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_vars$`NAs (%)`), "#27ae60", "#e74c3c"
))| Variável | Tipo | Valores Únicos | NAs (%) | Exemplo |
|---|---|---|---|---|
| faixa_etaria | character | 22 | 0.00% | 35 a 39 anos |
| idade | numeric | 120 | 0.00% | 36 |
| sexo | character | 4 | 0.00% | FEMININO |
| raca_cor | character | 6 | 0.61% | PARDA |
| municipio | character | 1 | 0.00% | RECIFE |
| grupo | character | 29 | 0.00% | TRABALHADORES DA SAÚDE |
| categoria | character | 170 | 89.52% | PESSOAS COM OBESIDADE MÓRBIDA (IMC > OU = 40) |
| lote | character | 656 | 0.07% | FM2951 |
| vacina_fabricante | character | 7 | 0.00% | COMIRNATY (PFIZER) |
| descricao_dose | factor | 6 | 0.00% | 1º Reforço |
| sistema_origem | character | 2 | 0.00% | Conecta Recife |
| data_vacinacao | Date | 361 | 0.00% | 2022-01-24 |
| distrito | character | 8 | 0.00% | DS 1 |
| unidade | character | 8 | 0.00% | POLICLÍNICA GOUVEIA DE BARROS |
| mes_vacinacao | Date | 12 | 0.00% | 2022-01-01 |
| distrito_cod | integer | 8 | 0.00% | 1 |
As variáveis podem ser divididas em três grupos. As demográficas
(faixa_etaria, idade, sexo e
raca_cor) descrevem o perfil do vacinado, com poucos
valores ausentes (menos de 0,1% em cada). As variáveis relacionadas à
campanha (grupo, categoria,
descricao_dose, vacina_fabricante,
distrito e unidade) descrevem o contexto da
aplicação; categoria permanece ausente em cerca de 89% dos
registros, o que é estrutural e não um problema de qualidade. Por fim, a
variável temporal data_vacinacao cobre o período de janeiro
de 2022 a dezembro de 2022, sem datas ausentes.