1 Introdução

Compreender como os registros de atuação da Defesa Civil se distribuem no tempo e no território pode apoiar discussões sobre a organização dos serviços e o acompanhamento das ações realizadas. Além do volume de registros, é necessário conhecer os tipos de ação e as condições de preenchimento da base, pois essas características influenciam as comparações entre períodos e locais.

Este projeto procura responder à seguinte pergunta: como os registros de atuação da Defesa Civil do Recife se distribuem entre meses, dias da semana, regionais e bairros em 2024, e como o perfil das ações varia entre esses recortes? Também se investiga em que medida as informações ausentes e as possíveis repetições limitam a interpretação dos resultados.

Para responder à pergunta, utiliza-se o arquivo de atendimentos de 2024 disponível no Portal de Dados Abertos do Recife. A abordagem consiste em uma análise exploratória em R, com importação, diagnóstico, padronização de textos, conversão de datas e números e seleção das ações com data em 2024. A partir da base preparada, calculam-se frequências, proporções, médias por dia de calendário e cruzamentos entre localização, período e tipo de ação. Tabelas e gráficos apresentam os resultados, acompanhados de interpretações.

A análise considera o preenchimento dos campos de tipo de ação e grau de risco e compara os resultados com um cenário que mantém apenas a primeira ocorrência de cada linha originalmente idêntica. Esses procedimentos permitem caracterizar a atuação registrada e avaliar a influência de algumas limitações da base.

Os resultados podem interessar a equipes de gestão e planejamento da Defesa Civil, pesquisadores e cidadãos que acompanham os serviços municipais. A identificação dos períodos com maior volume pode subsidiar discussões sobre a distribuição de recursos; a comparação das ações pode caracterizar o perfil registrado em cada regional; e a avaliação do preenchimento pode apontar necessidades de revisão dos registros. Como o estudo utiliza contagens administrativas, essas informações precisam ser interpretadas junto com suas limitações de cobertura e preenchimento.

2 Pacotes utilizados

O pacote readr importa arquivos CSV; dplyr permite manipular e resumir os dados; stringr padroniza textos; ggplot2 constrói os gráficos; e knitr apresenta as tabelas no relatório. Instale-os uma vez no Console antes de compilar o relatório.

# install.packages(c("readr", "dplyr", "stringr", "ggplot2", "knitr"))

library(readr)
library(dplyr)
library(stringr)
library(ggplot2)
library(knitr)

3 Descrição da base

Os dados foram obtidos no conjunto Registro de Atendimentos da Defesa Civil, disponibilizado gratuitamente no Portal de Dados Abertos da Prefeitura do Recife e vinculado à Secretaria Executiva de Defesa Civil. Segundo a descrição do portal, o conjunto reúne informações sobre solicitações de atendimento, áreas de risco, vistorias e execução de serviços de colocação de lona. O recurso “Atendimentos 2024” é apresentado como um registro das ações de monitoramento e atuação da Defesa Civil naquele ano. Sua natureza é administrativa: os dados documentam a atuação do serviço municipal, e este projeto os utiliza para análise exploratória.

O arquivo utilizado, atendimentos_2024.csv, foi baixado em 05/11/2026 e preservado em sua versão original. Ele contém 80.173 registros e 16 variáveis, em formato CSV, com ponto e vírgula como separador e codificação UTF-8. O ano de referência do recurso é 2024; a data de download indica quando a cópia foi obtida, sem representar a data de coleta de todos os registros. A documentação consultada não detalha o momento de inserção de cada linha no sistema.

As 16 colunas originais podem ser organizadas nos seguintes grupos:

Grupo Colunas originais Conteúdo identificado pelos campos
Referência temporal Ano, Mês, Data, Data_da_Acao Ano, mês e duas informações de data disponíveis para conferência e definição do recorte temporal.
Localização Regional, Endereco, Bairro, Localidade Identificação territorial e endereço associados ao registro.
Ocorrência, solicitação e ação Ocorrencia, Solicitacao, Tipo_da_Acao Informações sobre a ocorrência, a solicitação e a ação registrada.
Classificação de risco Grau_de_Risco Código de risco, quando preenchido.
Quantidades e medidas Quantidade, Altura, Largura, Area_m Campos quantitativos cuja interpretação depende do serviço e das regras de preenchimento.

O dicionário de dados consultado no portal lista os nomes e tipos dos campos, mas não esclarece suficientemente a unidade representada por cada linha nem as regras de classificação de risco e de preenchimento das medidas. Por isso, as contagens deste relatório representam registros do arquivo. Elas não são tratadas como quantidades de pessoas, imóveis ou solicitações únicas. As duas colunas de data também não são usadas para estimar tempo de resposta.

O arquivo combina textos, datas e valores de natureza numérica. Na importação, todas as colunas são lidas como texto para preservar sua representação antes das conversões explícitas. As datas observadas usam a ordem ano-mês-dia, e os campos numéricos podem apresentar ponto como separador decimal. Há campos vazios, diferenças de espaçamento e de maiúsculas e minúsculas e rótulos como “Nao Informado” e “Bairro Nao Cadastrado”, que indicam ausência de identificação do bairro. Esses rótulos exigem tratamento específico além do reconhecimento dos campos vazios.

Também são identificadas linhas originalmente idênticas e datas ausentes ou fora de 2024. A preparação sinaliza essas situações, preserva os valores originais e define o recorte pela coluna Data_da_Acao, posteriormente renomeada para data_acao. Zeros em campos quantitativos não são convertidos automaticamente em ausência, pois seu significado não foi confirmado. Essas particularidades orientam os tratamentos e os cuidados de interpretação apresentados nas seções seguintes.

4 Importação

Coloque atendimentos_2024.csv e este documento na mesma pasta. O CSV usa ponto e vírgula como separador. A leitura inicial utiliza texto para permitir conversões explícitas. A prévia limita a impressão a seis linhas.

arquivo <- "atendimentos_2024.csv"

if (!file.exists(arquivo)) {
  stop("CSV nao encontrado. Coloque-o na pasta do projeto ou ajuste 'arquivo'.")
}

# Ler como texto permite inspecionar os valores. Os numeros e as datas serao
# convertidos explicitamente, depois da inspecao.
dados_originais <- read_delim(
  arquivo,
  delim = ";",
  col_types = cols(.default = col_character()),
  locale = locale(encoding = "UTF-8"),
  na = c("", "NA"),
  trim_ws = FALSE,
  show_col_types = FALSE
)

dimensoes <- data.frame(
  registros = nrow(dados_originais),
  variaveis = ncol(dados_originais)
)
print(dimensoes)
##   registros variaveis
## 1     80173        16
print(head(dados_originais, 6))
## # A tibble: 6 × 16
##   Regional Ano   Mês   Data    Ocorrencia Solicitacao Endereco Bairro Localidade
##   <chr>    <chr> <chr> <chr>   <chr>      <chr>       <chr>    <chr>  <chr>     
## 1 Oeste    2024  Abril 2024-0… <NA>       <NA>        Rua Cap… Varzea Barreiras 
## 2 Nordeste 2024  Abril 2024-0… <NA>       Vistoria    Rua Cru… Guabi… Alto da G…
## 3 Nordeste 2024  Abril 2024-0… <NA>       Colocação … Subida … Nova … Alto da B…
## 4 Nordeste 2024  Abril 2024-0… <NA>       Colocação … Subida … Nova … Alto da B…
## 5 Nordeste 2024  Abril 2024-0… <NA>       Monitorame… Rua Alt… Nova … Alto da B…
## 6 Nordeste 2024  Abril 2024-0… <NA>       Monitorame… Rua Alt… Nova … Alto da B…
## # ℹ 7 more variables: Grau_de_Risco <chr>, Data_da_Acao <chr>,
## #   Tipo_da_Acao <chr>, Quantidade <chr>, Altura <chr>, Largura <chr>,
## #   Area_m <chr>

5 Diagnóstico inicial

A tabela abaixo informa os campos ausentes da base original, antes dos tratamentos. A marcação de repetições compara as colunas originais e preserva os registros para investigação.

diagnostico_ausencias <- data.frame(
  variavel = names(dados_originais),
  ausentes = colSums(is.na(dados_originais))
) %>%
  mutate(percentual = round(100 * ausentes / nrow(dados_originais), 2)) %>%
  arrange(desc(ausentes))
print(diagnostico_ausencias)
##                    variavel ausentes percentual
## Ocorrencia       Ocorrencia    77811      97.05
## Largura             Largura    70491      87.92
## Altura               Altura    70469      87.90
## Quantidade       Quantidade    68778      85.79
## Grau_de_Risco Grau_de_Risco    48812      60.88
## Solicitacao     Solicitacao    27536      34.35
## Tipo_da_Acao   Tipo_da_Acao    18918      23.60
## Bairro               Bairro       57       0.07
## Data_da_Acao   Data_da_Acao        8       0.01
## Data                   Data        1       0.00
## Regional           Regional        0       0.00
## Ano                     Ano        0       0.00
## Mês                     Mês        0       0.00
## Endereco           Endereco        0       0.00
## Localidade       Localidade        0       0.00
## Area_m               Area_m        0       0.00
repeticao_original <- duplicated(dados_originais)
print(data.frame(repeticoes_a_investigar = sum(repeticao_original)))
##   repeticoes_a_investigar
## 1                    5931

6 Padronização dos nomes e textos

A cópia de trabalho recebe nomes de colunas padronizados. O identificador id é criado com o número da linha e serve para localizar registros no arquivo, sem identificar solicitações únicas. Espaços extras e variações de maiúsculas são normalizados. Valores originais permanecem em dados_originais. As categorias de serviços com significados diferentes continuam separadas. Os rótulos de bairros não identificados são convertidos para NA.

dados <- dados_originais %>%
  rename(
    regional = Regional, ano_informado = Ano,
    mes_informado = `Mês`, data_registro = Data,
    ocorrencia = Ocorrencia, solicitacao = Solicitacao,
    endereco = Endereco, bairro = Bairro, localidade = Localidade,
    grau_risco = Grau_de_Risco, data_acao = Data_da_Acao,
    tipo_acao = Tipo_da_Acao, quantidade = Quantidade,
    altura = Altura, largura = Largura, area_m = Area_m
  ) %>%
  mutate(
    # Identificador criado para localizar cada linha do arquivo.
    id = row_number(),
    across(where(is.character), ~ na_if(str_squish(.x), "")),
    across(c(regional, bairro, localidade),
           ~ str_to_title(.x, locale = "pt")),
    across(c(ocorrencia, solicitacao, tipo_acao, mes_informado),
           ~ str_to_lower(.x, locale = "pt")),
    grau_risco = str_to_upper(grau_risco, locale = "pt"),
    possivel_repeticao_original = repeticao_original
  )

rotulos_sem_bairro <- c(
  "Nao Informado", "Não Informado", "Bairro Nao Cadastrado",
  "Bairro Não Cadastrado"
)
dados <- dados %>%
  mutate(bairro = if_else(bairro %in% rotulos_sem_bairro, NA_character_, bairro))

7 Conversão dos tipos e verificação das datas

Datas e números recebem os tipos adequados. Datas ausentes, inválidas, fora do período e ações anteriores à outra data são sinalizadas. Os anos não são alterados automaticamente.

dados <- dados %>%
  mutate(
    across(c(ano_informado, quantidade, altura, largura, area_m),
           ~ parse_double(.x, locale = locale(decimal_mark = "."))),
    data_registro_original = data_registro,
    data_acao_original = data_acao,
    data_registro = as.Date(substr(data_registro_original, 1, 10),
                            format = "%Y-%m-%d"),
    data_acao = as.Date(substr(data_acao_original, 1, 10),
                        format = "%Y-%m-%d"),
    data_registro_invalida = !is.na(data_registro_original) & is.na(data_registro),
    data_acao_invalida = !is.na(data_acao_original) & is.na(data_acao),
    data_registro_fora_2024 = !is.na(data_registro) &
      format(data_registro, "%Y") != "2024",
    data_acao_fora_2024 = !is.na(data_acao) &
      format(data_acao, "%Y") != "2024",
    acao_antes_registro = !is.na(data_registro) & !is.na(data_acao) &
      data_acao < data_registro,
    risco_informado = !is.na(grau_risco)
  )

# Nao corrigir os anos automaticamente nem interpretar a diferenca entre
# as datas como tempo de resposta sem confirmar suas definicoes na fonte.
diagnostico_datas <- dados %>%
  summarise(
    registro_sem_data = sum(is.na(data_registro)),
    acao_sem_data = sum(is.na(data_acao)),
    registro_invalido = sum(data_registro_invalida),
    acao_invalida = sum(data_acao_invalida),
    registro_fora_2024 = sum(data_registro_fora_2024),
    acao_fora_2024 = sum(data_acao_fora_2024),
    acao_anterior_ao_registro = sum(acao_antes_registro)
  )
print(diagnostico_datas)
## # A tibble: 1 × 7
##   registro_sem_data acao_sem_data registro_invalido acao_invalida
##               <int>         <int>             <int>         <int>
## 1                 1             8                 0             0
## # ℹ 3 more variables: registro_fora_2024 <int>, acao_fora_2024 <int>,
## #   acao_anterior_ao_registro <int>

8 Criação de variáveis e recorte temporal

Para a análise temporal, adota-se a data da ação como referência. Criam-se mês, trimestre, dia da semana e indicador de fim de semana. O subconjunto temporal inclui somente ações com data em 2024, enquanto a base preparada preserva todas as linhas. A tabela explicita o tamanho de cada conjunto.

meses <- c("Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho",
           "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro")
dias <- c("Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira",
          "Quinta-feira", "Sexta-feira", "Sábado")

dados <- dados %>%
  mutate(
    mes_numero = as.integer(format(data_acao, "%m")),
    mes_acao = factor(meses[mes_numero], levels = meses, ordered = TRUE),
    trimestre = (mes_numero - 1L) %/% 3L + 1L,
    dia_numero = as.integer(format(data_acao, "%w")),
    dia_semana = factor(dias[dia_numero + 1L], levels = dias, ordered = TRUE),
    fim_de_semana = if_else(is.na(dia_numero), NA,
                            dia_numero %in% c(0L, 6L))
  )

# Filtrar somente para as analises que usam a data da acao em 2024.
# A base 'dados' continua contendo todas as linhas, inclusive as sinalizadas.
dados_2024 <- dados %>%
  filter(!is.na(data_acao), format(data_acao, "%Y") == "2024")

print(data.frame(
  registros_originais = nrow(dados_originais),
  registros_preparados = nrow(dados),
  registros_com_acao_em_2024 = nrow(dados_2024),
  fora_do_recorte_temporal = nrow(dados) - nrow(dados_2024)
))
##   registros_originais registros_preparados registros_com_acao_em_2024
## 1               80173                80173                      80163
##   fora_do_recorte_temporal
## 1                       10
knitr::kable(
  dados_2024 %>%
    select(id, data_acao, regional, bairro, tipo_acao, grau_risco) %>%
    head(6),
  col.names = c("Linha", "Data da ação", "Regional", "Bairro", "Tipo de ação", "Risco"),
  caption = "Amostra dos registros após os tratamentos."
)
Amostra dos registros após os tratamentos.
Linha Data da ação Regional Bairro Tipo de ação Risco
1 2024-04-03 Oeste Varzea atendimento social NA
2 2024-04-16 Nordeste Guabiraba atendimento social R3
3 2024-04-16 Nordeste Nova Descoberta NA NA
4 2024-04-16 Nordeste Nova Descoberta NA NA
5 2024-04-16 Nordeste Nova Descoberta acoes de porta-porta R2
6 2024-04-16 Nordeste Nova Descoberta acoes de porta-porta R2

9 Síntese das variáveis utilizadas

A síntese abaixo descreve as principais variáveis do subconjunto dados_2024, após a padronização e o recorte pela data da ação. Os tipos apresentados são os utilizados no R. As variáveis de localização e ação permitem comparar grupos; as temporais organizam a distribuição ao longo do ano; e os indicadores de qualidade apoiam a interpretação e a comparação entre cenários.

Variável Tipo após o tratamento Significado e uso na análise
data_acao Data (Date) Data da ação informada na fonte; define o recorte de 2024 e origina as variáveis temporais.
regional Texto (character) Regional informada; permite comparar volume, composição das ações e preenchimento dos campos.
bairro Texto (character) Rótulo do bairro após a padronização; utilizado na análise de concentração territorial.
tipo_acao Texto (character) Categoria da ação registrada; utilizada nos rankings e nas comparações entre regionais e meses.
grau_risco Texto (character) Código de risco; sua distribuição é calculada entre os registros com o campo preenchido.
mes_acao Fator ordenado (ordered factor) Mês derivado de data_acao, ordenado de janeiro a dezembro; organiza tabelas e gráficos mensais.
dia_semana Fator ordenado (ordered factor) Dia da semana derivado de data_acao, com níveis de domingo a sábado; permite a comparação ajustada ao calendário.
risco_informado Lógico (logical) Indica se grau_risco está preenchido; utilizado na avaliação da cobertura desse campo.
possivel_repeticao_original Lógico (logical) Marca ocorrências posteriores de linhas originalmente idênticas; utilizado no cenário de sensibilidade às repetições.

A tabela seguinte consolida a diversidade dos valores e o preenchimento das sete variáveis que descrevem diretamente o período, a localização, a ação e o risco. Todos os percentuais de ausência usam o total de linhas de dados_2024. Os valores distintos contam somente os valores observados e não ausentes; níveis de fatores sem registros não aumentam essa contagem.

variaveis_interesse <- c(
  "data_acao", "regional", "bairro", "tipo_acao", "grau_risco",
  "mes_acao", "dia_semana"
)

sintese_variaveis <- data.frame(
  variavel = variaveis_interesse,
  valores_distintos = vapply(
    dados_2024[variaveis_interesse],
    function(x) n_distinct(x, na.rm = TRUE), integer(1)
  ),
  ausentes = vapply(
    dados_2024[variaveis_interesse],
    function(x) sum(is.na(x)), integer(1)
  ),
  row.names = NULL
) %>%
  mutate(percentual_ausente = 100 * ausentes / nrow(dados_2024))

knitr::kable(
  sintese_variaveis, digits = 1,
  col.names = c("Variável", "Valores distintos observados", "Ausentes", "% ausente"),
  caption = "Síntese das principais variáveis após o tratamento e o recorte temporal."
)
Síntese das principais variáveis após o tratamento e o recorte temporal.
Variável Valores distintos observados Ausentes % ausente
data_acao 273 0 0.0
regional 6 0 0.0
bairro 103 1352 1.7
tipo_acao 35 18918 23.6
grau_risco 4 48804 60.9
mes_acao 12 0 0.0
dia_semana 6 0 0.0

No recorte, as datas de ação vão de 02/01/2024 a 30/12/2024. Há 6 rótulos de regional e 103 rótulos de bairro preenchidos. Essas quantidades descrevem as categorias presentes no arquivo; a grafia dos bairros ainda não foi validada contra um cadastro oficial. A ausência em tipo_acao e grau_risco permanece identificada, sem imputação de categorias. Os códigos de risco são tratados como categorias, sem conversão em uma escala numérica de gravidade.

10 Resumos descritivos

As contagens usam o mesmo recorte temporal. A ausência do tipo de ação aparece como uma categoria própria, sem eliminar o registro. As contagens incluem os registros sinalizados como possíveis repetições.

resumo_mensal <- dados_2024 %>%
  count(mes_acao, name = "registros", .drop = FALSE)

resumo_regional <- dados_2024 %>%
  mutate(regional = coalesce(regional, "Não informada")) %>%
  count(regional, name = "registros", sort = TRUE) %>%
  mutate(percentual = round(100 * registros / sum(registros), 2))

resumo_acoes <- dados_2024 %>%
  mutate(tipo_acao = coalesce(tipo_acao, "não informado")) %>%
  count(tipo_acao, name = "registros", sort = TRUE)

print(resumo_mensal)
## # A tibble: 12 × 2
##    mes_acao  registros
##    <ord>         <int>
##  1 Janeiro        7313
##  2 Fevereiro      6463
##  3 Março         10559
##  4 Abril         12070
##  5 Maio           8790
##  6 Junho          7555
##  7 Julho          7628
##  8 Agosto         5764
##  9 Setembro       4116
## 10 Outubro        3873
## 11 Novembro       3072
## 12 Dezembro       2960
print(resumo_regional)
## # A tibble: 6 × 3
##   regional registros percentual
##   <chr>        <int>      <dbl>
## 1 Norte        20537       25.6
## 2 Noroeste     16075       20.0
## 3 Sul          14280       17.8
## 4 Oeste        12950       16.2
## 5 Nordeste      9110       11.4
## 6 Planície      7211        9
print(head(resumo_acoes, 10))
## # A tibble: 10 × 2
##    tipo_acao                      registros
##    <chr>                              <int>
##  1 atendimento social                 30080
##  2 não informado                      18918
##  3 acoes de porta-porta               15383
##  4 analise visual estrutural           7698
##  5 mapeamento de area de risco         2487
##  6 rocagem                             1954
##  7 encaminhamentos aos parceiros        848
##  8 distribuicao de cestas basicas       543
##  9 acoes educativas                     322
## 10 corte de arvores                     295

11 Visualização dos registros

Os gráficos mostram o volume mensal e a distribuição por regional das ações datadas em 2024. Eles devem ser interpretados como contagens de registros. Concentração de registros não equivale, por si só, a maior risco, maior população atendida ou maior eficiência do serviço.

grafico_mensal <- ggplot(resumo_mensal, aes(x = mes_acao, y = registros)) +
  geom_col(fill = "#28668A", width = 0.75) +
  labs(
    title = "Registros por mês da ação em 2024",
    x = "Mês", y = "Número de registros",
    caption = "Fonte: Defesa Civil do Recife. Possíveis repetições mantidas."
  ) +
  theme_minimal(base_size = 12) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

grafico_regional <- ggplot(
  resumo_regional, aes(x = reorder(regional, registros), y = registros)
) +
  geom_col(fill = "#287A62", width = 0.75) +
  coord_flip() +
  labs(
    title = "Registros por regional: ações datadas em 2024",
    x = "Regional", y = "Número de registros",
    caption = "Fonte: Defesa Civil do Recife. Possíveis repetições mantidas."
  ) +
  theme_minimal(base_size = 12)

print(grafico_mensal)

print(grafico_regional)

12 Distribuição temporal e cobertura do calendário

O recorte contém 80.163 registros, após deixar fora da análise temporal 10 linhas sem uma data de ação pertencente a 2024. As possíveis repetições permanecem no recorte. A comparação mensal considera o volume e a duração de cada mês. A média por dia de calendário inclui como zero os dias sem linhas no arquivo. Ela mede registros observados e não comprova ausência de atendimento nas datas sem linhas.

calendario_2024 <- data.frame(
  data_acao = seq(as.Date("2024-01-01"), as.Date("2024-12-31"), by = "day")
) %>%
  mutate(
    mes_numero = as.integer(format(data_acao, "%m")),
    dia_numero = as.integer(format(data_acao, "%w"))
  )

dias_por_mes <- calendario_2024 %>% count(mes_numero, name = "dias_calendario")
observado_por_mes <- dados_2024 %>%
  group_by(mes_numero) %>%
  summarise(registros = n(), dias_com_registro = n_distinct(data_acao),
            .groups = "drop")

atividade_mensal <- dias_por_mes %>%
  left_join(observado_por_mes, by = "mes_numero") %>%
  mutate(
    registros = coalesce(registros, 0L),
    dias_com_registro = coalesce(dias_com_registro, 0L),
    mes = factor(meses[mes_numero], levels = meses, ordered = TRUE),
    registros_por_dia = registros / dias_calendario
  )

knitr::kable(
  atividade_mensal %>%
    select(mes, registros, dias_calendario, dias_com_registro, registros_por_dia),
  digits = 1,
  col.names = c("Mês", "Registros", "Dias do mês", "Dias com registros",
                "Registros por dia de calendário"),
  caption = "Volume mensal e cobertura do calendário em 2024."
)
Volume mensal e cobertura do calendário em 2024.
Mês Registros Dias do mês Dias com registros Registros por dia de calendário
Janeiro 7313 31 23 235.9
Fevereiro 6463 29 20 222.9
Março 10559 31 23 340.6
Abril 12070 30 26 402.3
Maio 8790 31 25 283.5
Junho 7555 30 23 251.8
Julho 7628 31 25 246.1
Agosto 5764 31 25 185.9
Setembro 4116 30 23 137.2
Outubro 3873 31 22 124.9
Novembro 3072 30 19 102.4
Dezembro 2960 31 19 95.5
pico_mensal <- atividade_mensal %>% slice_max(registros, n = 1, with_ties = FALSE)
menor_mes <- atividade_mensal %>% slice_min(registros, n = 1, with_ties = FALSE)
pico_media_diaria <- atividade_mensal %>%
  slice_max(registros_por_dia, n = 1, with_ties = FALSE)
percentual_primeiro_semestre <- 100 *
  sum(atividade_mensal$registros[atividade_mensal$mes_numero <= 6]) / total_analise

Abril concentra o maior volume, com 12.070 registros. O menor volume aparece em Dezembro, com 2.960. O primeiro semestre reúne 65,8% dos registros. O pico da média por dia de calendário também ocorre em Abril, com 402,3 registros por dia. Assim, a diferença de duração entre os meses não explica sozinha o pico.

A redução de volume ao longo do ano pode envolver mudanças na atuação ou no preenchimento da base. Sem dados de chuva e outros anos, não é possível atribuir os picos à precipitação nem confirmar sazonalidade que se repete anualmente.

12.1 Dias da semana

Para comparar os dias da semana, divide-se o total de registros pela quantidade de ocorrências daquele dia no calendário. Alguns dias aparecem 53 vezes em 2024 e outros, 52 vezes. Datas sem linhas contribuem com zero registros observados.

dias_por_semana <- calendario_2024 %>% count(dia_numero, name = "dias_calendario")
observado_por_semana <- dados_2024 %>% count(dia_numero, name = "registros")

atividade_semanal <- dias_por_semana %>%
  left_join(observado_por_semana, by = "dia_numero") %>%
  mutate(
    registros = coalesce(registros, 0L),
    dia_semana = factor(dias[dia_numero + 1L], levels = dias, ordered = TRUE),
    registros_por_dia = registros / dias_calendario
  )

knitr::kable(
  atividade_semanal %>% select(dia_semana, registros, dias_calendario, registros_por_dia),
  digits = 1,
  col.names = c("Dia da semana", "Registros", "Dias no calendário", "Registros por dia")
)
Dia da semana Registros Dias no calendário Registros por dia
Domingo 0 52 0.0
Segunda-feira 14221 53 268.3
Terça-feira 13651 53 257.6
Quarta-feira 13203 52 253.9
Quinta-feira 16373 52 314.9
Sexta-feira 10724 52 206.2
Sábado 11991 52 230.6
ggplot(atividade_semanal, aes(x = dia_semana, y = registros_por_dia)) +
  geom_col(fill = "#28668A", width = 0.75) +
  labs(title = "Registros por dia da semana, ajustados ao calendário",
       x = "Dia da semana", y = "Registros por dia de calendário",
       caption = "Médias sobre todos os dias de 2024, com ou sem linhas na base.") +
  theme_minimal(base_size = 12) +
  theme(axis.text.x = element_text(angle = 35, hjust = 1))

pico_semanal <- atividade_semanal %>%
  slice_max(registros_por_dia, n = 1, with_ties = FALSE)
nomes_sem_registro <- as.character(
  atividade_semanal$dia_semana[atividade_semanal$registros == 0]
)

Quinta-feira apresenta a maior média, com 314,9 registros por dia de calendário. Os dias da semana sem registros no recorte são: Domingo. Essa ausência é uma característica do arquivo e não permite concluir que a Defesa Civil deixou de funcionar nesses dias. Há registros em 273 das 366 datas do ano.

13 Concentração dos registros por bairro

A análise utiliza os rótulos de bairro após a padronização dos textos. Registros sem identificação do bairro são apresentados separadamente. Os percentuais usam como denominador todos os registros do recorte, inclusive aqueles com bairro ausente.

registros_sem_bairro <- sum(is.na(dados_2024$bairro))
ranking_bairros <- dados_2024 %>%
  filter(!is.na(bairro)) %>%
  count(bairro, name = "registros", sort = TRUE) %>%
  mutate(percentual_total = 100 * registros / total_analise,
         percentual_acumulado = cumsum(percentual_total))

top_bairros <- ranking_bairros %>% slice_head(n = 10)
participacao_top5 <- sum(head(ranking_bairros$registros, 5)) / total_analise * 100

knitr::kable(
  top_bairros, digits = 1,
  col.names = c("Bairro informado", "Registros", "% do total", "% acumulado"),
  caption = "Dez rótulos de bairro com maior volume de registros."
)
Dez rótulos de bairro com maior volume de registros.
Bairro informado Registros % do total % acumulado
Cohab 13269 16.6 16.6
Dois Unidos 10620 13.2 29.8
Nova Descoberta 7666 9.6 39.4
Varzea 5545 6.9 46.3
Agua Fria 3726 4.6 50.9
Vasco Da Gama 3458 4.3 55.2
Linha Do Tiro 3430 4.3 59.5
Ibura 3416 4.3 63.8
Jordao 2701 3.4 67.2
Macaxeira 2438 3.0 70.2
ggplot(top_bairros, aes(x = reorder(bairro, registros), y = registros)) +
  geom_col(fill = "#287A62", width = 0.75) +
  coord_flip() +
  labs(title = "Bairros com maior volume de registros",
       x = "Bairro informado", y = "Número de registros",
       caption = "Dez maiores categorias com bairro preenchido. Repetições mantidas.") +
  theme_minimal(base_size = 12)

Os três rótulos mais frequentes são Cohab, Dois Unidos, Nova Descoberta. Os cinco primeiros concentram 50,9% do total. Outros 1.352 registros (1,7%) não possuem bairro identificado após o tratamento dos rótulos de ausência.

Essa concentração localiza os bairros mais presentes na base. Comparações de risco exigiriam denominadores como população exposta ou imóveis acompanhados. Também podem permanecer variações de grafia: os rótulos não foram validados contra um cadastro oficial de bairros.

14 Tipos de ação e diferenças entre regionais

Para comparar regionais de tamanhos distintos, calcula-se a participação das ações dentro de cada regional. Destacam-se as quatro ações preenchidas mais frequentes no recorte. As demais são agrupadas apenas nos gráficos em “Outras ações”. O grupo “Não informado” permanece separado e a base detalhada preserva as categorias originais.

ranking_acoes <- dados_2024 %>%
  filter(!is.na(tipo_acao)) %>%
  count(tipo_acao, name = "registros", sort = TRUE) %>%
  mutate(percentual_total = 100 * registros / total_analise)

knitr::kable(
  head(ranking_acoes, 6), digits = 1,
  col.names = c("Tipo de ação", "Registros", "% de todos os registros"),
  caption = "Ações preenchidas mais frequentes; ausências fora desta tabela."
)
Ações preenchidas mais frequentes; ausências fora desta tabela.
Tipo de ação Registros % de todos os registros
atendimento social 30080 37.5
acoes de porta-porta 15383 19.2
analise visual estrutural 7698 9.6
mapeamento de area de risco 2487 3.1
rocagem 1954 2.4
encaminhamentos aos parceiros 848 1.1
acoes_principais <- head(ranking_acoes$tipo_acao, 4)
grupos_acoes <- c(str_to_sentence(acoes_principais, locale = "pt"),
                 "Outras ações", "Não informado")

dados_com_grupos <- dados_2024 %>%
  mutate(
    grupo_acao = case_when(
      is.na(tipo_acao) ~ "Não informado",
      tipo_acao %in% acoes_principais ~ str_to_sentence(tipo_acao, locale = "pt"),
      TRUE ~ "Outras ações"
    ),
    grupo_acao = factor(grupo_acao, levels = grupos_acoes)
  )

composicao_regional <- dados_com_grupos %>%
  count(regional, grupo_acao, name = "registros", .drop = FALSE) %>%
  group_by(regional) %>%
  mutate(percentual = 100 * registros / sum(registros)) %>%
  ungroup()

cobertura_acoes <- dados_2024 %>%
  group_by(regional) %>%
  summarise(total = n(), informados = sum(!is.na(tipo_acao)),
            nao_informados = sum(is.na(tipo_acao)), .groups = "drop") %>%
  mutate(percentual_informado = 100 * informados / total) %>%
  arrange(desc(percentual_informado))

knitr::kable(
  cobertura_acoes, digits = 1,
  col.names = c("Regional", "Registros", "Ação informada", "Não informada",
                "% com ação informada"),
  caption = "Cobertura do preenchimento do tipo de ação por regional."
)
Cobertura do preenchimento do tipo de ação por regional.
Regional Registros Ação informada Não informada % com ação informada
Planície 7211 7207 4 99.9
Sul 14280 14255 25 99.8
Noroeste 16075 14691 1384 91.4
Nordeste 9110 6743 2367 74.0
Oeste 12950 7933 5017 61.3
Norte 20537 10416 10121 50.7
cores_acoes <- setNames(
  c("#28668A", "#287A62", "#C58D2F", "#8266A4", "#AABBC7", "#DDDDDD"),
  grupos_acoes
)

ggplot(composicao_regional, aes(x = regional, y = percentual, fill = grupo_acao)) +
  geom_col(width = 0.75) +
  coord_flip() +
  scale_fill_manual(values = cores_acoes,
                    labels = function(x) str_wrap(x, width = 25), drop = FALSE) +
  scale_y_continuous(labels = function(x) paste0(x, "%")) +
  labs(title = "Composição das ações registradas por regional",
       x = "Regional", y = "Percentual dos registros da regional", fill = "Ação",
       caption = "Denominador: todos os registros de cada regional, incluindo ausências.") +
  guides(fill = guide_legend(nrow = 3, byrow = TRUE)) +
  theme_minimal(base_size = 11) +
  theme(legend.position = "bottom")

acao_predominante <- ranking_acoes %>% slice_head(n = 1)
maior_cobertura_acao <- cobertura_acoes %>% slice_head(n = 1)
menor_cobertura_acao <- cobertura_acoes %>% slice_tail(n = 1)

# O denominador dos contrastes inclui todos os registros de cada regional.
social_noroeste <- dados_2024 %>% filter(regional == "Noroeste") %>%
  summarise(percentual = 100 * sum(tipo_acao == "atendimento social", na.rm = TRUE) / n())
estrutural_sul <- dados_2024 %>% filter(regional == "Sul") %>%
  summarise(percentual = 100 * sum(tipo_acao == "analise visual estrutural", na.rm = TRUE) / n())

Entre as ações preenchidas, atendimento social é a mais frequente, com 30.080 registros e 37,5% de todos os registros. Atendimento social representa 63,3% dos registros da Noroeste. Na Sul, análise visual estrutural representa 39,3% do total regional.

A cobertura de preenchimento do tipo de ação varia de 50,7% em Norte a 99,9% em Planície. Diferenças na composição podem refletir tanto a atuação registrada quanto diferenças de preenchimento.

14.1 Como a composição muda entre os meses

O mapa de calor usa os mesmos grupos de ação. Cada coluna soma 100% e representa a composição dos registros de um mês. As cores indicam percentuais, permitindo comparar a participação das ações mesmo quando o volume mensal é diferente.

composicao_mensal <- dados_com_grupos %>%
  count(mes_acao, grupo_acao, name = "registros", .drop = FALSE) %>%
  group_by(mes_acao) %>%
  mutate(percentual = 100 * registros / sum(registros)) %>%
  ungroup()

ggplot(composicao_mensal, aes(x = mes_acao, y = grupo_acao, fill = percentual)) +
  geom_tile(color = "white", linewidth = 0.4) +
  scale_fill_gradient(low = "#F2F6F8", high = "#155A7E", name = "% no mês") +
  scale_y_discrete(limits = rev(grupos_acoes),
                   labels = function(x) str_wrap(x, width = 24)) +
  labs(title = "Participação dos grupos de ação nos registros mensais",
       x = "Mês da ação", y = NULL,
       caption = "As participações incluem a categoria de ação não informada.") +
  theme_minimal(base_size = 11) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
        panel.grid = element_blank())

peso_social_mensal <- dados_2024 %>%
  group_by(mes_numero) %>%
  summarise(
    percentual = 100 * sum(tipo_acao == "atendimento social", na.rm = TRUE) / n(),
    .groups = "drop"
  )

A participação do atendimento social passa de 26,0% em janeiro para 73,1% em dezembro. O aumento da participação não significa, por si só, aumento do número absoluto de atendimentos sociais: o total de registros e o preenchimento das outras ações também variam. O resultado descreve uma mudança no perfil relativo da base ao longo de 2024.

15 Grau de risco e limites do preenchimento

A distribuição dos códigos deve ser analisada junto com a cobertura do campo. Ausência de classificação não equivale a ausência de risco. Os códigos são apresentados como constam no arquivo, sem atribuir significados de gravidade que não foram validados na documentação.

total_risco_informado <- sum(dados_2024$risco_informado)
percentual_risco_informado <- 100 * total_risco_informado / total_analise

distribuicao_risco <- dados_2024 %>%
  filter(risco_informado) %>%
  count(grau_risco, name = "registros") %>%
  mutate(percentual_informados = 100 * registros / sum(registros)) %>%
  arrange(grau_risco)

cobertura_risco <- dados_2024 %>%
  group_by(regional) %>%
  summarise(total = n(), informados = sum(risco_informado),
            nao_informados = sum(!risco_informado), .groups = "drop") %>%
  mutate(percentual_informado = 100 * informados / total) %>%
  arrange(desc(percentual_informado))

knitr::kable(
  distribuicao_risco, digits = 1,
  col.names = c("Código de risco", "Registros", "% dos riscos preenchidos"),
  caption = "Distribuição restrita aos registros com grau de risco preenchido."
)
Distribuição restrita aos registros com grau de risco preenchido.
Código de risco Registros % dos riscos preenchidos
R1 2829 9.0
R2 10727 34.2
R3 16467 52.5
R4 1336 4.3
knitr::kable(
  cobertura_risco, digits = 1,
  col.names = c("Regional", "Registros", "Risco informado", "Não informado",
                "% com risco informado"),
  caption = "Cobertura do grau de risco por regional."
)
Cobertura do grau de risco por regional.
Regional Registros Risco informado Não informado % com risco informado
Noroeste 16075 10856 5219 67.5
Nordeste 9110 5324 3786 58.4
Oeste 12950 5498 7452 42.5
Norte 20537 5874 14663 28.6
Sul 14280 3095 11185 21.7
Planície 7211 712 6499 9.9
risco_frequente <- distribuicao_risco %>%
  slice_max(registros, n = 1, with_ties = FALSE)

O grau de risco está preenchido em 31.359 registros, equivalentes a 39,1% do recorte. Entre esses registros, o código R3 é o mais frequente, com 52,5% das classificações preenchidas. A participação se refere ao subconjunto classificado e não pode ser generalizada automaticamente para os registros sem informação.

A cobertura varia entre regionais. Um menor número de classificações pode estar associado a menor preenchimento. A tabela não permite ordenar as regionais por risco real.

16 Sensibilidade às possíveis repetições

Compara-se a base principal a um cenário que mantém apenas a primeira ocorrência de cada combinação de valores originais. Esse cenário não comprova que todas as linhas repetidas sejam erros e não transforma registros em solicitações ou pessoas únicas. A finalidade é verificar se as repetições alteram os resultados.

dados_sem_repeticoes <- dados_2024 %>% filter(!possivel_repeticao_original)

comparacao_regionais <- dados_2024 %>%
  group_by(regional) %>%
  summarise(com_repeticoes = n(),
            sem_repeticoes = sum(!possivel_repeticao_original), .groups = "drop") %>%
  mutate(
    percentual_com = 100 * com_repeticoes / sum(com_repeticoes),
    percentual_sem = 100 * sem_repeticoes / sum(sem_repeticoes),
    diferenca_pp = percentual_sem - percentual_com
  ) %>%
  arrange(desc(com_repeticoes))

knitr::kable(
  comparacao_regionais, digits = 1,
  col.names = c("Regional", "Com repetições", "Sem repetições", "% com",
                "% sem", "Diferença (p.p.)"),
  caption = "Participação regional nos dois cenários; cada cenário tem seu total."
)
Participação regional nos dois cenários; cada cenário tem seu total.
Regional Com repetições Sem repetições % com % sem Diferença (p.p.)
Norte 20537 18131 25.6 24.4 -1.2
Noroeste 16075 15683 20.1 21.1 1.1
Sul 14280 13106 17.8 17.7 -0.2
Oeste 12950 12010 16.2 16.2 0.0
Nordeste 9110 8900 11.4 12.0 0.6
Planície 7211 6402 9.0 8.6 -0.4
ranking_com <- comparacao_regionais %>% arrange(desc(com_repeticoes)) %>% pull(regional)
ranking_sem <- comparacao_regionais %>% arrange(desc(sem_repeticoes)) %>% pull(regional)
mes_pico_sem_repeticoes <- dados_sem_repeticoes %>%
  count(mes_acao, name = "registros") %>%
  slice_max(registros, n = 1, with_ties = FALSE)
repeticoes_no_recorte <- sum(dados_2024$possivel_repeticao_original)

O cenário alternativo contém 74.232 registros, uma redução de 5.931 linhas (7,4%). A ordem das regionais por volume permanece igual. O mês com maior volume no cenário alternativo é Abril, com 10.593 registros.

Essa comparação distingue conclusões mantidas nos dois cenários de valores absolutos que dependem da política de tratamento. A base principal continua preservando todas as linhas do recorte temporal.

17 Conclusões

A análise descreveu a distribuição dos registros de atuação da Defesa Civil do Recife datados em 2024. A preparação envolveu padronização de textos, conversão de tipos, tratamento dos rótulos de ausência e marcação de possíveis repetições e inconsistências de data. O recorte foi definido pela data da ação.

O primeiro semestre reúne 65,8% dos registros, e o pico ocorre em Abril. Os cinco rótulos de bairro mais frequentes concentram 50,9% do total. O perfil das ações varia entre regionais e meses, mas sua interpretação depende do preenchimento dos campos.

A classificação de risco cobre 39,1% dos registros, limitando a generalização dos resultados desse campo. O cenário sem repetições exatas mantém o pico mensal em Abril, e a ordem regional permanece igual.

17.1 Implicações para o planejamento e a qualidade dos registros

Para as equipes de gestão, a concentração de registros no primeiro semestre e o pico em Abril oferecem uma referência histórica para comparar o volume de atuação registrado com as escalas de trabalho e a disponibilidade de materiais naquele período. Essa comparação pode subsidiar a revisão da preparação operacional. A definição de uma escala para anos seguintes exige verificar se o padrão se mantém em outros anos e considerar a capacidade do serviço e as condições locais.

No território, a concentração nos cinco rótulos de bairro mais frequentes pode orientar a seleção de locais para examinar com mais detalhe os tipos de ação realizados e a cobertura do registro. Antes de utilizar esse ranking para distribuir recursos, seria necessário validar os nomes dos bairros e relacionar os volumes à população exposta, aos imóveis acompanhados e a informações de risco. Essa etapa permitiria avaliar se a concentração decorre do tamanho da área atendida, do perfil da atuação ou de diferenças na forma de registrar.

O contraste entre atendimento social na Noroeste (63,3% dos registros da regional) e análise visual estrutural na Sul (39,3%) fornece um ponto de partida para discutir a composição das atividades em cada regional. As equipes podem confrontar esse perfil com suas atribuições e rotinas de trabalho, examinando necessidades de articulação entre atendimento social e atividades de vistoria. A comparação deve considerar as diferenças de preenchimento do tipo de ação antes de orientar mudanças na organização das equipes.

Na qualidade dos dados, a regional Norte apresenta a menor cobertura de preenchimento do tipo de ação (50,7%). Esse resultado indica um ponto para revisar o fluxo de lançamento e conferir os critérios de preenchimento com os responsáveis pelos registros. Como o grau de risco está informado em 39,1% do recorte, também é necessário distinguir os casos em que o campo não se aplica daqueles em que houve falha de preenchimento. A revisão pode incluir orientações por tipo de ação, motivos de ausência e padronização das categorias.

Por fim, a ausência de registros em certos dias da semana deve motivar uma conferência da cobertura do arquivo e da rotina de lançamento antes de qualquer avaliação sobre escalas de atendimento. As linhas originalmente idênticas também precisam ser confrontadas com o processo que gera os dados antes de uma decisão de exclusão. A comparação entre cenários mostra quais resultados se mantêm apesar dessas repetições.

17.2 Limitações e possibilidades de aprofundamento

O estudo não estima risco por habitante, produtividade ou número de pessoas atendidas. As limitações incluem ausências de preenchimento, possíveis repetições, rótulos territoriais ainda não validados e desconhecimento da cobertura do sistema de registro. Outros anos e dados territoriais e meteorológicos permitiriam investigar explicações para os padrões observados, sem atribuir causalidade às associações descritivas.