1. Introdução e Objetivos

1.1 Contexto

Este projeto analisa dados de permissões de construção (Building Permits) da cidade de São Francisco, Califórnia, cobrindo um período de 5 anos (janeiro de 2013 a fevereiro de 2018) com aproximadamente 200.000 registros.

Uma permissão de construção é um documento oficial de aprovação emitido por uma agência governamental que permite ao proprietário ou contratante prosseguir com um projeto de construção ou reforma em sua propriedade. Cada cidade ou condado possui seu próprio departamento relacionado a edificações, que desempenha múltiplas funções como emissão de permissões, inspeção de edifícios para garantir medidas de segurança, e modificação de regulamentos para acomodar as necessidades da população em crescimento.

O dataset foi obtido no Kaggle (Building Permit Applications Data) e contém 43 colunas com informações detalhadas sobre cada permissão emitida, incluindo tipo de permissão, localização, custos estimados, datas de solicitação e aprovação, status, e informações do solicitante.

1.2 Base de Dados

O dataset consiste em um único arquivo contendo 43 colunas e aproximadamente 200.000 registros de permissões de construção. As principais categorias de informações incluem:

Informações Temporais: - Datas de solicitação, emissão, aprovação e conclusão - Tempo de processamento das permissões

Informações de Localização: - Endereço completo - Número do bloco e lote - Coordenadas geográficas (latitude e longitude) - Distrito supervisor - Bairro

Informações do Projeto: - Tipo de permissão - Situação da permissão - Descrição do trabalho proposto - Número de unidades existentes e propostas - Custo estimado do projeto

Informações Administrativas: - Número da permissão - Número da solicitação - Informações do solicitante - Departamento responsável

Dados Estruturais: - Tipo de construção - Uso existente e proposto da propriedade

1.3 Objetivos

Este projeto visa realizar uma análise exploratória dos dados de permissões de construção de San Francisco para extrair insights sobre o processo de aprovação, padrões de desenvolvimento urbano e eficiência administrativa. Os objetivos específicos são:

Análise Temporal:

  • Analisar o tempo de processamento para diferentes tipos de permissões
  • Identificar tendências anuais no volume de solicitações e aprovações

Análise de Tipos de Permissões:

  • Caracterizar os diferentes tipos de permissões e suas frequências
  • Analisar a distribuição de status das permissões

Análise Geográfica:

  • Explorar a distribuição espacial das permissões pela cidade
  • Identificar áreas com maior atividade de construção

Análise de Custos:

  • Examinar a distribuição de custos estimados dos projetos
  • Relacionar custos com tipos de permissões

2. Pacotes Requeridos

# Pacotes
library(tidyverse)
library(lubridate)

3. Preparação dos Dados

3.1 Descrição das Colunas

O dataset de Building Permits contém 43 colunas. Abaixo estão descritas todas as colunas do dataset:

Identificação e Tipo da Permissão
  • Permit Number: Número atribuído durante o protocolo da permissão
  • Permit Type: Tipo da permissão representado numericamente
  • Permit Type Definition: Descrição do tipo de permissão, por exemplo, nova construção, alterações
  • Record ID: Identificador do registro (não útil para análise)
Informações Temporais
  • Permit Creation Date: Data em que a permissão foi criada, posterior ou igual à data de protocolo
  • Filed Date: Data de protocolo da permissão
  • Issued Date: Data de emissão da permissão
  • Completed Date: Data em que o projeto foi concluído, aplicável se Current Status = “completed”
  • First Construction Document Date: Data em que a construção foi documentada
  • Permit Expiration Date: Data de expiração relacionada à permissão emitida
  • Current Status Date: Data em que o status atual foi registrado
Status e Acompanhamento
  • Current Status: Status atual da solicitação de permissão
  • Structural Notification: Notificação para atender alguma necessidade legal, dada ou não
Localização do Imóvel
  • Block: Relacionado ao endereço
  • Lot: Relacionado ao endereço
  • Street Number: Relacionado ao endereço
  • Street Number Suffix: Relacionado ao endereço
  • Street Name: Relacionado ao endereço
  • Street Name Suffix: Relacionado ao endereço
  • Unit: Unidade de um edifício
  • Unit suffix: Sufixo, se houver, para a unidade
  • Zipcode: CEP do endereço do edifício
  • Supervisor District: Distrito supervisor ao qual a localização do edifício pertence
  • Neighborhoods - Analysis Boundaries: Bairro ao qual a localização do edifício pertence
  • Location: Localização em par de latitude e longitude
Descrição do Projeto
  • Description: Detalhes sobre o propósito da permissão. Exemplo: recobertura, renovação de banheiro
Características do Edifício - Existentes
  • Number of Existing Stories: Número de andares existentes no edifício. Não aplicável para certos tipos de permissão
  • Existing Use: Uso existente do edifício
  • Existing Units: Número existente de unidades
  • Existing Construction Type: Tipo de construção existente, como categorias representadas numericamente
  • Existing Construction Type Description: Descrição do tipo acima, por exemplo, madeira ou outros tipos de construção
Características do Edifício - Propostas
  • Number of Proposed Stories: Número de andares propostos para a construção/alteração
  • Proposed Use: Uso proposto do edifício
  • Proposed Units: Número proposto de unidades
  • Proposed Construction Type: Tipo de construção proposta, como categorias representadas numericamente
  • Proposed Construction Type Description: Descrição do tipo acima
Custos do Projeto
  • Estimated Cost: Estimativa inicial do custo do projeto
  • Revised Cost: Estimativa revisada do custo do projeto
Regulamentações e Conformidade
  • Voluntary Soft-Story Retrofit: Andar flexível para atender regulamentos de terremoto
  • Fire Only Permit: Permissão relacionada à prevenção de risco de incêndio
  • TIDF Compliance: Conformidade com TIDF ou não, este é um novo requisito legal
  • Site Permit: Permissão para o local
Documentação
  • Plansets: Representação do plano indicando a intenção geral de design da fundação

3.2 Carregamento e Importação dos Dados

Nesta etapa, realizaremos a importação do dataset de Building Permits para o ambiente R. O processo inclui:

  1. Definição do caminho: Especificar o diretório onde o arquivo CSV está armazenado
  2. Importação: Utilizar a função read.csv() com parâmetros adequados
  3. Conversão de tipos de dados:
    • Converter colunas de data de string para objetos Date/POSIXct
    • Converter custos para valores numéricos
    • Processar coordenadas geográficas
  4. Tratamento de valores ausentes: Identificar e tratar NAs de forma apropriada
  5. Remoção de colunas inutilizadas: Excluir colunas que não serão relevantes para a análise (como Record ID e outras redundantes)
  6. Criação de variáveis derivadas:
    • Calcular tempo de processamento (Issued Date - Filed Date)
    • Criar categorias para análises agregadas
  7. Filtragem e limpeza: Remover registros inconsistentes ou duplicados

Detalhe:

  • Valores ausentes são comuns em colunas opcionais como Completed Date, Unit, Revised Cost
  • Coordenadas geográficas estão em formato de string e necessitam parsing
  • Custos podem conter valores zero ou NA para projetos sem estimativa
# 1. Definição do caminho e 2. Importação
permits <- read.csv("Building_Permits.csv", stringsAsFactors = FALSE)

# 3. Conversão de tipos de dados
# Converter datas usando lubridate
permits <- permits %>%
  mutate(
    Filed.Date = mdy(Filed.Date),
    Issued.Date = mdy(Issued.Date),
    Completed.Date = mdy(Completed.Date),
    Permit.Creation.Date = mdy(Permit.Creation.Date),
    Permit.Expiration.Date = mdy(Permit.Expiration.Date)
  )

# Converter custos para numérico
permits <- permits %>%
  mutate(
    Estimated.Cost = as.numeric(Estimated.Cost),
    Revised.Cost = as.numeric(Revised.Cost)
  )

# Processar coordenadas geográficas
# A coluna Location está no formato "(lat, long)". Vamos limpar e separar.
permits <- permits %>%
  mutate(Location_Clean = gsub("[()]", "", Location)) %>%
  separate(Location_Clean, into = c("Latitude_Parsed", "Longitude_Parsed"), sep = ", ", convert = TRUE, remove = FALSE)

# 4. Tratamento de valores ausentes
# Vamos verificar NAs em colunas chave.
# Para este exercício, vamos manter os NAs em
# datas (pois indicam processos não finalizados)
# e custos (pois podem ser desconhecidos).

permits$Number.of.Existing.Stories[is.na(permits$Number.of.Existing.Stories)] <- 0
permits$Proposed.Units[is.na(permits$Proposed.Units)] <- 0
permits$Proposed.Construction.Type[is.na(permits$Proposed.Construction.Type)] <- 0
permits$Existing.Units[is.na(permits$Existing.Units)] <- 0
permits$Existing.Construction.Type[is.na(permits$Existing.Construction.Type)] <- 0
permits$Number.of.Proposed.Stories[is.na(permits$Number.of.Proposed.Stories)] <- 0

# 5. Remoção de colunas inutilizadas
permits <- permits %>%
  select(-Record.ID)

# 6. Criação de variáveis derivadas
permits <- permits %>%
  mutate(
    # Tempo de processamento em dias
    Processing_Time = as.numeric(difftime(Issued.Date, Filed.Date, units = "days")),
    # Categoria de custo
    Cost_Category = as.factor(case_when(
      Estimated.Cost < 5000 ~ "Baixo (<5k)",
      Estimated.Cost < 50000 ~ "Médio (5k-50k)",
      Estimated.Cost < 1000000 ~ "Alto (50k-1M)",
      Estimated.Cost >= 1000000 ~ "Muito Alto (>1M)",
      TRUE ~ "Desconhecido"
    ))
  )

# 7. Filtragem e limpeza
permits <- permits %>%
  # Remove linhas duplicadas
  distinct() %>%
  # Remove registros sem número de permissão se houver
  filter(!is.na(Permit.Number))

4. Análise Exploratória

4.1 Análise Temporal

Nesta seção, analisamos o tempo de processamento das permissões e as tendências anuais.

Tempo de Processamento por Tipo de Permissão

# Resumo do tempo de processamento
summary(permits$Processing_Time)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    0.00    0.00    0.00   26.05    6.00 1740.00   14928
# Visualização do tempo de processamento por tipo (limitando outliers para visualização)
permits %>%
  filter(!is.na(Processing_Time), !is.na(Permit.Type.Definition)) %>%
  ggplot(aes(x = reorder(Permit.Type.Definition, Processing_Time, FUN = median), y = Processing_Time)) +
  geom_boxplot() +
  coord_flip() +
  labs(title = "Tempo de Processamento por Tipo de Permissão",
       x = "Tipo de Permissão",
       y = "Dias até Emissão") +
  theme_minimal() +
  scale_y_log10() # Escala logarítmica para melhor visualização

Tendências Anuais

# Extrair ano de Filed.Date e Issued.Date
permits_annual <- permits %>%
  mutate(
    Filed_Year = year(Filed.Date),
    Issued_Year = year(Issued.Date)
  )

# Contagem por ano (Solicitações)
filed_counts <- permits_annual %>%
  filter(!is.na(Filed_Year)) %>%
  count(Filed_Year) %>%
  mutate(Type = "Solicitadas")

# Contagem por ano (Emitidas)
issued_counts <- permits_annual %>%
  filter(!is.na(Issued_Year)) %>%
  count(Issued_Year, name = "n") %>% 
  rename(Filed_Year = Issued_Year) %>% 
  mutate(Type = "Emitidas")

# Combinar e plotar
bind_rows(filed_counts, issued_counts) %>%
  filter(Filed_Year >= 2013, Filed_Year <= 2018) %>% # Focar no período principal
  ggplot(aes(x = Filed_Year, y = n, color = Type)) +
  geom_line(size = 1) +
  geom_point() +
  labs(title = "Volume Anual de Permissões: Solicitadas vs Emitidas",
       x = "Ano",
       y = "Quantidade",
       color = "Status") +
  theme_minimal()

4.2 Análise de Tipos de Permissões

Investigamos a frequência dos diferentes tipos de permissões e seus status atuais.

# Frequência de Tipos de Permissão
permits %>%
  count(Permit.Type.Definition, sort = TRUE) %>%
  ggplot(aes(x = reorder(Permit.Type.Definition, n), y = n)) +
  geom_col(fill = "steelblue") +
  coord_flip() +
  labs(title = "Frequência dos Tipos de Permissão",
       x = "Tipo de Permissão",
       y = "Contagem") +
  theme_minimal()

# Distribuição de Status
permits %>%
  count(Current.Status, sort = TRUE) %>%
  top_n(10, n) %>% # Top 10 status mais comuns
  ggplot(aes(x = reorder(Current.Status, n), y = n)) +
  geom_col(fill = "darkgreen") +
  coord_flip() +
  labs(title = "Top 10 Status Atuais das Permissões",
       x = "Status",
       y = "Contagem") +
  theme_minimal()

4.3 Análise Geográfica

Exploramos a distribuição espacial das permissões em São Francisco.

# Mapa de pontos (Scatter plot das coordenadas)
permits %>%
  filter(!is.na(Latitude_Parsed), !is.na(Longitude_Parsed)) %>%
  filter(Neighborhoods...Analysis.Boundaries != "") %>%
  # Filtrar coordenadas inválidas (SF approx: Lat 37.7, Long -122.4)
  filter(Latitude_Parsed > 37, Latitude_Parsed < 38, Longitude_Parsed > -123, Longitude_Parsed < -122) %>%
  ggplot(aes(x = Longitude_Parsed, y = Latitude_Parsed, color = Neighborhoods...Analysis.Boundaries)) +
  geom_point(alpha = 0.5, size = 0.5) +
  labs(title = "Distribuição Espacial das Permissões por Bairro",
       x = "Longitude",
       y = "Latitude",
       color = "Bairro") +
  coord_quickmap() +
  theme_minimal() +
  theme(legend.position = "none") # Legenda removida para evitar poluição visual

# Top Bairros
# Nota: O nome da coluna de bairro é assumido como 'Neighborhoods...Analysis.Boundaries'
permits %>%
  count(Neighborhoods...Analysis.Boundaries, sort = TRUE) %>%
  top_n(15, n) %>%
  filter(Neighborhoods...Analysis.Boundaries != "") %>%
  ggplot(aes(x = reorder(Neighborhoods...Analysis.Boundaries, n), y = n)) +
  geom_col(fill = "orange") +
  coord_flip() +
  labs(title = "Top 15 Bairros com Mais Permissões",
       x = "Bairro",
       y = "Contagem") +
  theme_minimal()

Distribuição Espacial de Custos

# Mapa de calor de custos
permits %>%
  filter(!is.na(Latitude_Parsed), !is.na(Longitude_Parsed), !is.na(Estimated.Cost)) %>%
  filter(Latitude_Parsed > 37, Latitude_Parsed < 38, Longitude_Parsed > -123, Longitude_Parsed < -122) %>%
  arrange(Estimated.Cost) %>%
  ggplot(aes(x = Longitude_Parsed, y = Latitude_Parsed, color = Estimated.Cost)) +
  geom_point(alpha = 0.5, size = 0.5) +
  scale_color_viridis_c(trans = "log10", labels = scales::dollar) +
  labs(title = "Distribuição Espacial de Custos (Escala Log)",
       x = "Longitude",
       y = "Latitude",
       color = "Custo Estimado") +
  coord_quickmap() +
  theme_minimal()

4.4 Análise de Custos

Examinamos os custos estimados dos projetos.

# Distribuição de Custos Estimados (Histograma)
permits %>%
  filter(!is.na(Estimated.Cost), Estimated.Cost > 10) %>%
  ggplot(aes(x = Estimated.Cost)) +
  geom_histogram(bins = 50, fill = "firebrick", color = "white") +
  scale_x_log10(labels = scales::dollar) +
  labs(title = "Distribuição dos Custos Estimados (Escala Log)",
       x = "Custo Estimado (USD)",
       y = "Frequência") +
  theme_minimal()

# Custo por Tipo de Permissão
permits %>%
  filter(!is.na(Estimated.Cost), Estimated.Cost > 10, !is.na(Permit.Type.Definition)) %>%
  ggplot(aes(x = reorder(Permit.Type.Definition, Estimated.Cost, FUN = median), y = Estimated.Cost)) +
  geom_boxplot() +
  scale_y_log10(labels = scales::dollar) +
  coord_flip() +
  labs(title = "Distribuição de Custos por Tipo de Permissão",
       x = "Tipo de Permissão",
       y = "Custo Estimado (USD)") +
  theme_minimal()

Custo Médio por Bairro

# Custo Médio por Bairro
permits %>%
  filter(!is.na(Estimated.Cost), Neighborhoods...Analysis.Boundaries != "") %>%
  group_by(Neighborhoods...Analysis.Boundaries) %>%
  summarise(
    Avg_Cost = mean(Estimated.Cost, na.rm = TRUE),
    Median_Cost = median(Estimated.Cost, na.rm = TRUE),
    Count = n()
  ) %>%
  filter(Count > 50) %>% # Filtrar bairros com poucas observações para robustez
  top_n(15, Avg_Cost) %>%
  ggplot(aes(x = reorder(Neighborhoods...Analysis.Boundaries, Avg_Cost), y = Avg_Cost)) +
  geom_col(fill = "darkred") +
  coord_flip() +
  scale_y_continuous(labels = scales::dollar) +
  labs(title = "Top 15 Bairros por Custo Médio Estimado",
       subtitle = "Considerando apenas bairros com > 50 permissões",
       x = "Bairro",
       y = "Custo Médio") +
  theme_minimal()

Taxa de Emissão por Custo

# Taxa de Emissão por Faixa de Custo Estimado
permits %>%
  filter(!is.na(Estimated.Cost), Estimated.Cost > 10) %>%
  mutate(Issued_Flag = ifelse(!is.na(Issued.Date), 1, 0)) %>%
  ggplot(aes(x = Estimated.Cost, y = Issued_Flag)) +
  stat_summary_bin(fun = "mean", geom = "bar", bins = 50, fill = "steelblue", color = "white") +
  scale_x_log10(labels = scales::dollar) +
  scale_y_continuous(labels = scales::percent) +
  labs(title = "Taxa de Emissão por Custo Estimado",
       x = "Custo Estimado (USD)",
       y = "Porcentagem Emitida") +
  theme_minimal()

5. Conclusão

Com base nas análises realizadas, podemos concluir que:

  • A quantidade de permissões solicitadas e emitidas vai crescendo com o passar dos anos;
  • Vemos que os as permissões que mais demoram a ser emitidas são de novas construções e demolições;
  • A maior parte das permissões solicidatas são do tipo OTC(Over-the-Counter), que são alterações simples e não estruturais que não necessitam de revisão ou vistorias;
  • A maior parte das permissões emitidas não foram finalizadas até o fim da data do dataset;
  • O bairro com mais permissões emitidas é South Beach;
  • O custo estimado segue uma distribuição normal;
  • A media de custo do bairro de Mission Bay é o dobro do segundo bairro com maior média de gastos;
  • Não há uma correlação entre o custo estimado e a taxa de emissão, indicando que o custo estimado não é um bom indicador da taxa de emissão;