Indicadores imobiliários de Juiz de Fora:

Análise de dados do ITBI.

Guilherme Ferreira

2024-12-06

Introdução

Indicadores de transações imobiliárias em Juiz de Fora/MG podem ser elaborados a partir de dados do ITBI (Imposto sobre Transmissão de Bens Imóveis) disponibilizados pela Prefeitura Municipal.

O acesso a essas estatísticas e indicadores pode auxiliar os agentes do mercado na tomada de decisões.

Atualmente, a base de dados é limitada, pois inclui apenas transações dos dois últimos exercícios fiscais encerrados, o que dificulta a produção de estimativas amplamente representativas.

Espera-se que a divulgação dessas informações seja mantida nos próximos anos, permitindo a criação de uma base de dados mais robusta.

Objetivo

Inspirados no projeto da FIPE, buscamos desenvolver indicadores imobiliários que possam contribuir para o fortalecimento do ambiente de negócios local.

Recursos

Os dados podem ser obtidos em:
https://pjf.mg.gov.br/transparencia/dados_abertos/itbi/index.php.
Último acesso em: 12/11/2024.

Disclaimer

Os dados são utilizados para fins educacionais; contudo, embora sejam abertos ao público, respeitamos os princípios de confidencialidade e privacidade, de modo que as matrículas foram omitidas ou anonimizadas, para evitar a identificação dos imóveis ou proprietários.

Bibliotecas

Carregamos as seguintes bibilotecas do R:

  • rvest - biblioteca para extração de dados web;
  • tidyverse - coleção de ferramentas para manipulação de dados;
  • lubridate - biblioteca para manipular dados no formato data/hora;
  • prettydoc - temas adicionais para documentos Rmarkdown;
  • reshape2 - ferramenta para transformação de dados;
  • scales - utilizada para personalizar legendas;
  • DT - para incluir tabelas em relatórios Rmarkdown;
  • treemapify - para representação de dados usando retângulos aninhados;
  • readxl - pacote para manipulação de dados do Excel.

Diretório de trabalho

Definimos o diretório de trabalho:

setwd("/home/gf/Scripts/ITBI")

Coleta de dados

Criamos uma função para baixar os arquivos e extrair as tabelas:

# Definir o diretório de trabalho
setwd("/home/gf/Scripts/ITBI/")

# Função para baixar e ler o arquivo xls, verificando se já existe localmente
baixar_itbi_xls <- function(ano) {
  # URL do arquivo xls com base no ano
  url <- paste0(
    "https://pjf.mg.gov.br/transparencia/dados_abertos/itbi/arquivos/xls/", 
    ano, ".xls")
  
  # Nome do arquivo local
  arquivo_xls <- file.path(getwd(), paste0("itbi_", ano, ".xls"))
  
  # Verifica se o arquivo já existe no diretório
  if (!file.exists(arquivo_xls)) {
    # Se não existir, faz o download do arquivo
    tryCatch(
      {
        download.file(url, destfile = arquivo_xls, mode = "wb")
      },
      error = function(e) {
        message(paste("Erro ao baixar o arquivo para o ano", ano, ":", e$message))
        return(NULL)  # Retorna NULL em caso de erro para evitar continuar com leitura
      }
    )
  } else {
    message(paste("O arquivo", arquivo_xls, "já existe no diretório. Pulando download."))
  }
  
  # Verifica novamente se o arquivo foi baixado com sucesso
  if (file.exists(arquivo_xls)) {
    # Ler o arquivo xls usando readxl
    dados <- read_excel(arquivo_xls)
    # Adicionar uma coluna com o ano
    dados$Ano <- ano
    return(dados)
  } else {
    message("Arquivo não disponível para o ano ", ano)
    return(NULL)
  }
}

Armazenamos os data frames em listas:

tabelas <- list()

Iteramos para baixar os arquivos xls de 2022 e 2023:

for (ano in 2022:2023) {
  tabela <- baixar_itbi_xls(ano)
  tabelas[[as.character(ano)]] <- tabela
}
## O arquivo /home/gf/Scripts/ITBI/itbi_2022.xls já existe no diretório. Pulando download.
## O arquivo /home/gf/Scripts/ITBI/itbi_2023.xls já existe no diretório. Pulando download.

Convertemos a coluna ‘DATA TRANSAÇÃO’ para o tipo Date:

tabelas[["2022"]] <- tabelas[["2022"]] %>%
  mutate("DATA TRANSAÇÃO" = dmy(`DATA TRANSAÇÃO`))

Combinamos todas as tabelas em um único data frame:

df <- bind_rows(tabelas %>% type.convert(as.is=TRUE))

Formatamos a coluna ‘DATA TRANSAÇÃO’:

df <- df %>%
  mutate(`DATA TRANSAÇÃO` = as.Date(`DATA TRANSAÇÃO`, format = "%Y-%m-%d"))

Renomeamos as colunas:

df <- df %>% 
  rename(
   INSCRIÇÃO = "INSCRIÇÃO REDUZIDA",
   LOGRADOURO = `TIPO VIA`,
   OPERAÇÃO = `NATUREZA DA OPERAÇÃO`,
   VALOR = `VALOR DA TRANSAÇÃO`,
   DATA = `DATA TRANSAÇÃO`,
   SFH = `CONTRATO COM AGENTE DO SFH`
   )

Selecionamos as colunas desejadas:

df <- df %>% 
  mutate (INSCRIÇÃO = substr(INSCRIÇÃO, 1, 4)) %>%
  select(INSCRIÇÃO, OPERAÇÃO, DATA, SFH)

Validação dos dados

Detectamos a existência de valores ausentes:

A função is.na() detecta valores ausentes e retorna o objeto booleano True, se positivo ou False, se negativo.

any(is.na(df))
## [1] TRUE

Identificamos as colunas com valores ausentes:

A função apply() aplica a função any(is.na(x)) em todas as colunas do data frame, para retornar o objeto booleano indicativo da existência ou não de valores ausentes.

apply(df, 2, function(x) any(is.na(x)))
## INSCRIÇÃO  OPERAÇÃO      DATA       SFH 
##     FALSE      TRUE     FALSE     FALSE

Identificamos as colunas com valores zerados:

A função colSums() é usada para contar quantos valores iguais a zero existem em cada coluna do data frame.

colSums(df==0)
## INSCRIÇÃO  OPERAÇÃO      DATA       SFH 
##         0        NA         0         0

Removemos as linhas com valores ausentes:

df <- df[complete.cases(df), ]

Visualizamos o data frame final:

  datatable(df, list(iDisplayLength = 5))

Indicadores de transações imobiliárias

Quantidade acumulada de transações por tipo de operação

operações <- count(df, OPERAÇÃO, sort = TRUE)

datatable(operações, list(iDisplayLength = 10))
operações <- count(df, OPERAÇÃO, sort = TRUE)

library(treemapify)
ggplot(operações, aes(area = n, fill = OPERAÇÃO,
                      label = paste(OPERAÇÃO, scales::number(n,
                                                             decimal.mark = ",",
                                                             big.mark = "."), 
                      sep = "\n"))) +
  geom_treemap() +
  geom_treemap_text(colour = "white",
                    place = "centre",
                    size = 15) +
  theme(legend.position = "none") 

Evolução mensal de transações imobiliárias

transações <- df %>%
  mutate(DATA = format(as.Date(DATA), "%Y-%m")) %>%
  filter(DATA >= "2022-01") %>%
  group_by(DATA) %>%
  summarise(Total = n())

compra_e_venda <- df %>%
  mutate(DATA = format(as.Date(DATA), "%Y-%m")) %>%
  filter(DATA >= "2022-01",
         OPERAÇÃO == "COMPRA E VENDA") %>%
  group_by(DATA) %>%
  summarise(Vendas = n())

series <- transações %>% 
  left_join(compra_e_venda, by = "DATA")

series <- series %>%
  mutate(DATA = as.Date(paste0(DATA, "-01")))

ggplot(series, aes(x=DATA)) +
  geom_line(aes(y = Total, color = "Todas as transações"), linewidth = 1) +
  geom_line(aes(y = Vendas, color = "Compra e Venda"), linewidth = 1, linetype = "dashed") +
  labs(
    title = "Série temporal de operações imobiliárias",
    x = "Data",
    y = "Contagem") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
  theme(plot.title = element_text(lineheight=.8, face="bold", size = 12)) +
  theme(text = element_text(size=10)) +
  scale_color_manual(values = c("Todas as transações" = "blue", "Compra e Venda" = "red")) +
  scale_x_date(limit=as.Date(c("2022-01-01","2023-10-01")), breaks="1 month", labels=date_format("%Y-%m"))

Quantidade mensal de transações imobiliárias por ano

# Filtrar os dados para o ano de 2022
series_2022 <- series %>%
  filter(format(DATA, "%Y") == "2022") %>%
  pivot_longer(cols = c("Total", "Vendas"), names_to = "Tipo", values_to = "Contagem") %>%
  mutate(Tipo = dplyr::recode(Tipo, "Total" = "Todas as transações", "Vendas" = "Compra e Venda")) # Renomeia as categorias
# Criar o gráfico de barras com as barras lado a lado por DATA
ggplot(series_2022, aes(x = DATA, y = Contagem, fill = Tipo)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(
    title = "Quantidade mensal de registros - 2022",
    x = "DATA",
    y = "Contagem",
    fill = "Tipo"
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
  theme(plot.title = element_text(lineheight=.8, face="bold", size = 12)) +
  theme(text = element_text(size=10)) +
  scale_x_date(limit=as.Date(c("2021-12-01","2023-01-01")), breaks="1 month", labels=date_format("%Y-%m"))

  # Filtrar os dados para o ano de 2023
series_2023 <- series %>%
  filter(format(DATA, "%Y") == "2023") %>%
  pivot_longer(cols = c("Total", "Vendas"), names_to = "Tipo", values_to = "Contagem") %>%
  mutate(Tipo = dplyr::recode(Tipo, "Total" = "Todas as transações", "Vendas" = "Compra e Venda")) # Renomeia as categorias
# Criar o gráfico de barras com as barras lado a lado por DATA
ggplot(series_2023, aes(x = DATA, y = Contagem, fill = Tipo)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(
    title = "Quantidade mensal de registros - 2023",
    x = "DATA",
    y = "Contagem",
    fill = "Tipo"
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
  theme(plot.title = element_text(lineheight=.8, face="bold", size = 12)) +
  theme(text = element_text(size=10)) +
  scale_x_date(limit=as.Date(c("2022-12-01","2023-12-01")), breaks="1 month", labels=date_format("%Y-%m"))

Quantidade anual de transações imobiliárias

# Agregar os dados por ano, somando o Total e Vendas
# Calcular a proporção de Vendas sobre Total e agregar dados
series_ano <- series %>%
  mutate(Ano = lubridate::year(DATA)) %>%
  group_by(Ano) %>%
  summarise(
    Total = sum(Total, na.rm = TRUE),
    Vendas = sum(Vendas, na.rm = TRUE)
  ) %>%
  mutate(Proporção = Vendas / Total) %>%  # Adiciona a coluna de proporção
  pivot_longer(cols = c("Total", "Vendas"), names_to = "Tipo", values_to = "Contagem") %>%
  mutate(Tipo = dplyr::recode(Tipo, "Total" = "Todas as transações", "Vendas" = "Compra e Venda")) # Renomeia as categorias
# Criar o gráfico de barras com as barras lado a lado por ano
# Criar o gráfico com labels
ggplot(series_ano, aes(x = as.factor(Ano), y = Contagem, fill = Tipo)) +
  geom_bar(stat = "identity", position = "dodge") +
  geom_text(aes(label = Contagem), position = position_dodge(width = 0.9), vjust = -0.3) + # Labels verticais
  geom_text(
    data = series_ano %>% filter(Tipo == "Todas as transações"), # Filtrar apenas uma vez por ano para a proporção
    aes(label = scales::percent(Proporção, accuracy = 0.1), x = as.factor(Ano), y = max(Contagem) / 2), 
    position = position_dodge(width = 0.9),
    vjust = 0.5,
    color = "black"
  ) +
  labs(
    title = "Quantidade anual de registros",
    x = "Ano",
    y = "Contagem",
    fill = "Tipo"
  ) +
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
  theme(plot.title = element_text(lineheight=.8, face="bold", size = 12)) +
  theme(text = element_text(size=10)) 

Evolução mensal de consolidação de propriedade

consolidação <- df %>%
  mutate(MÊS = format(as.Date(DATA), "%Y-%m")) %>%
  filter(MÊS >= "2022-01",
         OPERAÇÃO == "CONSOLIDACAO DE PROPRIEDADE") %>%
  group_by(MÊS) %>%
  summarise(Quantidade = n())

# Converte o MÊS para formato de data (primeiro dia de cada mês)
consolidação$MÊS <- as.Date(paste0(consolidação$MÊS, "-01"))

# Gerar o gráfico de linhas
ggplot(consolidação, aes(x = MÊS, y = Quantidade)) +
  geom_line(color = "red", linewidth = 1) +
  labs(
    title = "Série temporal da consolidação de propriedade",
    x = "Mês",
    y = "Quantidade de registros"
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
  theme(plot.title = element_text(lineheight=.8, face="bold", size = 12)) +
  theme(text = element_text(size=10)) +
  scale_x_date(limit=as.Date(c("2022-01-01","2023-10-01")), breaks="1 month", labels=date_format("%Y-%m"))