1 Utilizando uma abordagem dividida em passos

Antes de iniciar a análise para o projeto Spatial-Statistics-Applications, alguns importantes passos foram realizados para preparação da fonte de dados. Estes passos foram descritos nos tópicos a seguir.

O processo preparação de dados, em geral, inclui etapas de extração (retirar os dados de sua localização atual), tranformação (limpar e normalizar os dados) e carga (colocar os dados em um banco de dados onde eles podem ser analisados).

1.1 Step 01: Configuração do ambiente

Passo que executa configurações iniciais para execução dos passos seguintes.

# clearing everything before starting -----------------------------------------
# clear environment and memory
rm(list = ls()[ls() != 'data_prep_full'])
invisible(gc())

# clear console screen
cat("\014")

# clear plots
while (!is.null(dev.list()))  
  dev.off()

# setting the environment -----------------------------------------------------
options(encoding = "UTF-8")

info.username  <- Sys.info()[["user"]]
info.sysname   <- Sys.info()[["sysname"]]
info.machine   <- Sys.info()[["machine"]]
info.encoding  <- getOption("encoding")
directoryPath  <- dirname(rstudioapi::getSourceEditorContext()$path)
directoryPath  <- stringr::str_replace(directoryPath, "/src/datapreparation", "")

setwd(directoryPath)
getwd()


# setting up google maps API key for ggmaps -----------------------------------

# before you recalculate the dataset, make sure you have set up you google maps API below
register_google(key = "your-key-goes-here")

# to check current API key in use run:
# google_key()

# to supress API key in the console run:
# ggmap_hide_api_key()

# to show API key in the console run:
# ggmap_show_api_key()

1.2 Step 02: Ingestão dos dados

A etapa de ingestão de dados - data ingestion - é responsável por carregar os dados da fonte de dados de origem.

# performing data loading

# unzip required raw data sources ----

files_to_unzip <- c('data/raw/IBGE/br_municipios.zip', 
                    'data/raw/BIZROG_ZNMT2017_2019_Publ_10.4.zip')

for (file_to_unzip in files_to_unzip) {
  unzip(file_to_unzip, 
        exdir = tools::file_path_sans_ext(file_to_unzip), 
        overwrite = FALSE)
}

unzip('data/processed/gas_prices_hist/gas_prices_hist.zip', 
      exdir = 'data/processed/gas_prices_hist', overwrite = FALSE)

# import gas prices weekly historical ----

gas_prices_hist <- read_xlsx('data/raw/ANP_precos_gasolina/SEMANAL_MUNICIPIOS-2020.xlsx',
                             col_names = as.character(c(1:19)))

gas_prices_hist$`INTERVALO DE TEMPO` <- gas_prices_hist[[7, 1]]
gas_prices_hist$`INTERVALO DE TEMPO` <- 
  str_remove_all(gas_prices_hist$`INTERVALO DE TEMPO`, 'INTERVALO DE TEMPO: ')

gas_prices_hist$`PERÍODO` <- gas_prices_hist[[8, 1]]
gas_prices_hist$`PERÍODO` <- str_remove_all(gas_prices_hist$PERÍODO, 'PERÍODO: ')

gas_prices_hist$`COMBUSTÍVEL` <- gas_prices_hist[[9, 1]]
gas_prices_hist$`COMBUSTÍVEL` <- str_remove_all(gas_prices_hist$COMBUSTÍVEL, 'COMBUSTÍVEL: ')

gas_prices_hist$`TIPO RELATÓRIO` <- gas_prices_hist[[10, 1]]
gas_prices_hist$`TIPO RELATÓRIO` <- 
  str_remove_all(gas_prices_hist$`TIPO RELATÓRIO`, 'TIPO RELATÓRIO: ')

names(gas_prices_hist)[1:19] <- as.character(as.vector(gas_prices_hist[13, 1:19]))

gas_prices_hist <- gas_prices_hist[14:nrow(gas_prices_hist), ]

gas_prices_hist <- type_convert(gas_prices_hist,
                                col_types = cols(
                                  .default = col_character(),
                                  `DATA INICIAL` = col_integer(),
                                  `DATA FINAL` = col_integer(),
                                  `NÚMERO DE POSTOS PESQUISADOS` = col_integer(),
                                  `PREÇO MÉDIO REVENDA` = col_double(),
                                  `DESVIO PADRÃO REVENDA` = col_double(),
                                  `PREÇO MÍNIMO REVENDA` = col_double(),
                                  `PREÇO MÁXIMO REVENDA` = col_double(),
                                  `MARGEM MÉDIA REVENDA` = col_double(),
                                  `PREÇO MÉDIO DISTRIBUIÇÃO` = col_double(),
                                  `PREÇO MÉDIO DISTRIBUIÇÃO` = col_double(),
                                  `DESVIO PADRÃO DISTRIBUIÇÃO` = col_double(),
                                  `PREÇO MÍNIMO DISTRIBUIÇÃO` = col_double(),
                                  `PREÇO MÁXIMO DISTRIBUIÇÃO` = col_double(),
                                  `COEF DE VARIAÇÃO REVENDA` = col_double(),
                                  `COEF DE VARIAÇÃO DISTRIBUIÇÃO` = col_double()
                                ), 
                                na = '-')

gas_prices_hist$`DATA INICIAL` <- excel_numeric_to_date(gas_prices_hist$`DATA INICIAL`)
gas_prices_hist$`DATA FINAL` <- excel_numeric_to_date(gas_prices_hist$`DATA FINAL`)

names(gas_prices_hist) <- str_to_lower(make.names(names(gas_prices_hist)))

# import gas prices by gas station ----

files <- list.files('data/raw/ANP_precos_gasolina', full.names = TRUE)
files <- files[str_detect(files, 
                          'data/raw/ANP_precos_gasolina/RelatorioResumoPorMunicipioPosto*?')]

gas_prices_station <- tibble()

for (file in files) {

  df <- read_xlsx(file, col_names = as.character(c(1:9)))
  
  df$CIDADE <- df[[5, 1]]
  df$CIDADE <- str_remove_all(df$CIDADE, 'Síntese dos Preços Praticados - ')
  
  df$PRODUTO <- df[[6, 1]]
  df$PRODUTO <- str_match(df$PRODUTO, '- (.*?) R')[,2]
  
  df$`UNIDADE DE MEDIDA` <- df[[6, 1]]
  df$`UNIDADE DE MEDIDA` <- str_match(df$`UNIDADE DE MEDIDA`, 
                                                      paste('(?<= ' , 
                                                            df$PRODUTO[1], 
                                                            ' ).*(?! ', 
                                                            df$PRODUTO[1] , 
                                                            ' )', 
                                                            sep = ''))
  
  df$`DATA INICIAL` <- df[[7, 1]]
  df$`DATA INICIAL` <- str_match(df$`DATA INICIAL`, 'e (.*?) ')[,2]
  
  df$`DATA FINAL` <- df[[7, 1]]
  df$`DATA FINAL` <- str_match(df$`DATA FINAL`, '(?<= a ).*(?! a )')
  
  names(df)[1:9] <- as.character(as.vector(df[10, 1:9]))

  names(df)[8] <- 'fornecedor'
  
  df <- df[11:nrow(df), ]
  
  names(df) <- make.names(names(df))

  df <- filter(df, !is.na(DATA.COLETA))
  
  df <- type_convert(df,
                     col_types = cols(.default = col_character(),
                                      PREÇO.VENDA = col_double(),
                                      PREÇO.COMPRA = col_double(),
                                      DATA.COLETA = col_date(format = '%d/%m/%Y'),
                                      DATA.INICIAL = col_date(format = '%d/%m/%Y'),
                                      DATA.FINAL = col_date(format = '%d/%m/%Y')), 
                     na = '-')
  
  df$PREÇO.COMPRA <- df$PREÇO.COMPRA / 1000
  df$PREÇO.VENDA  <- df$PREÇO.VENDA / 1000

  gas_prices_station <- bind_rows(gas_prices_station, df)

}

names(gas_prices_station) <- str_to_lower(names(gas_prices_station))

names(gas_prices_station)[names(gas_prices_station) == 'modelidade.de.compra'] <- 
  'modalidade.de.compra'

rm(df, file, files)
invisible(gc())

# load mnemonic ----

gas_prices_hist_header <- read_xlsx('data/processed/mnemonico.xlsx', 
                                    sheet = 'gas_prices_hist')

gas_prices_station_header <- read_xlsx('data/processed/mnemonico.xlsx', 
                                       sheet = 'gas_prices_station')

PIB_header <- read_xlsx('data/processed/mnemonico.xlsx',
                        sheet = 'PIB')

POP_header <- read_xlsx('data/processed/mnemonico.xlsx',
                        sheet = 'Pop')

# import PIB data ----

pib <- read_xls('data/raw/IBGE/PIB dos Municípios - base de dados 2010-2017.xls', 
                col_names = PIB_header$mnemonico, 
                skip = 1)

pib$CodIBGE <- as.character(pib$CodIBGE)

# import POP data ----

pop <- read_xls('data/raw/IBGE/estimativa_TCU_2019_20200427.xls', 
                col_names = POP_header$mnemonico, 
                sheet = 'Municípios', 
                skip = 2)

pop$CodIBGE <- paste(pop$CdUF, pop$CodIBGE, sep = '')

1.3 Step 03: Tratamento dos dados

O objetivo desta etapa é analisar valores ausentes (missing values) e outras condições estranhas.

# analysing missing values and other strange conditions -----------------------

# For this project, this step was not required.

# clean POP dataset ----

pop <- filter(pop, !is.na(pop$CdUF))

1.4 Step 04: Aprimoramento dos dados

O objetivo desta etapa é aprimorar os dados adicionando novas informações que agreguem nas explorações dos mesmos.

# this step aims to improve the analysis by adding auxiliary information ------

# create_master_cidade_estado ----

master_cidade_estado <- tibble(estado = gas_prices_hist$estado,
                               cidade = gas_prices_hist$município)

master_cidade_estado <- distinct(master_cidade_estado)


# adding estado to gas_prices_station ----

gas_prices_station$estado <- plyr::mapvalues(gas_prices_station$cidade, 
                                             master_cidade_estado$cidade, 
                                             master_cidade_estado$estado, 
                                             warn_missing = FALSE)

# adding IBGE city code in gas_prices datasets ----

cities <- readOGR('data/raw/IBGE/br_municipios/BRMUE250GC_SIR.dbf', 
                  encoding = 'UTF-8', 
                  use_iconv = TRUE, 
                  stringsAsFactors = FALSE)

cities@data$NM_MUNICIP <- iconv(cities@data$NM_MUNICIP, to = 'ASCII//TRANSLIT')

UFs <- readOGR('data/raw/IBGE/br_unidades_da_federacao/BRUFE250GC_SIR.dbf', 
               encoding = 'UTF-8', 
               use_iconv = TRUE, 
               stringsAsFactors = FALSE)

UFs@data$NM_ESTADO    <- iconv(UFs@data$NM_ESTADO, to = 'ASCII//TRANSLIT')

cities@data$CD_GEOCUF  <- str_sub(cities@data$CD_GEOCMU, 1, 2)
cities@data$NM_ESTADO  <- plyr::mapvalues(cities@data$CD_GEOCUF, 
                                          UFs@data$CD_GEOCUF, 
                                          UFs@data$NM_ESTADO)

gas_prices_station$codigo.ibge <- plyr::mapvalues(paste(gas_prices_station$estado, 
                                                        gas_prices_station$cidade), 
                                                  paste(cities@data$NM_ESTADO, 
                                                        cities@data$NM_MUNICIP), 
                                                  cities@data$CD_GEOCMU, 
                                                  warn_missing = FALSE)

gas_prices_hist$codigo.ibge <- plyr::mapvalues(paste(gas_prices_hist$estado, gas_prices_hist$município), 
                                               paste(cities@data$NM_ESTADO, cities@data$NM_MUNICIP), 
                                               cities@data$CD_GEOCMU, warn_missing = FALSE)

# fix manual do codigo do IBGE (não encontrou no shapefile do IBGE por causa de caracter especial)
gas_prices_hist$codigo.ibge <- if_else(gas_prices_hist$codigo.ibge == 'RIO GRANDE DO SUL SANTANA DO LIVRAMENTO', 
                                         '4317103', 
                                         gas_prices_hist$codigo.ibge)


# adding geocoding using ggmap library ----

gas_prices_station$place <- paste(gas_prices_station$endereço,
                                  gas_prices_station$bairro,
                                  gas_prices_station$cidade,
                                  gas_prices_station$estado,
                                  'BRAZIL', sep = ', ')

gas_prices_station <- mutate_geocode(gas_prices_station, place)

gas_prices_station <- filter(gas_prices_station, !(lon < -78))

# adding adding index to gas_prices dataset ----

gas_prices_station <- rowid_to_column(gas_prices_station, 'station.id')
gas_prices_hist <- rowid_to_column(gas_prices_hist, 'index')

1.5 Step 05: Preparação dos datasets

Como último passo de preparação de dados, o dataset final é salvo em formato .rds para uso nos demais relatórios e scripts.

# dataset preparation ---------------------------------------------------------

# fix shape files created in QGIS ----

shp_gas_prices_station <- readOGR('data/processed/gas_prices_station/gas_prices_station.dbf',
                                  encoding = 'UTF-8',
                                  use_iconv = TRUE,
                                  stringsAsFactors = FALSE)

shp_gas_prices_hist <- readOGR('data/processed/gas_prices_hist/gas_prices_hist.dbf',
                               encoding = 'UTF-8', 
                               use_iconv = TRUE, 
                               stringsAsFactors = FALSE)

names(shp_gas_prices_hist@data) <- gas_prices_hist_header$mnemonico
names(shp_gas_prices_station@data) <- gas_prices_station_header$mnemonico
 
shp_gas_prices_station@data$StationID %<>% as.integer()
shp_gas_prices_station@data$PcVenda %<>% as.double()
shp_gas_prices_station@data$PcCompra %<>% as.double()
shp_gas_prices_station@data$Lon %<>% as.double()
shp_gas_prices_station@data$Lat %<>% as.double()
shp_gas_prices_station@data$DtColeta %<>% as_date(format = '%Y-%m-%d', tz = "America/Sao_Paulo")
shp_gas_prices_station@data$DtFinal %<>% as_date(format = '%Y-%m-%d', tz = "America/Sao_Paulo")
shp_gas_prices_station@data$DtInicial %<>% as_date(format = '%Y-%m-%d', tz = "America/Sao_Paulo")
 
shp_gas_prices_hist@data$Index %<>% as.integer()
shp_gas_prices_hist@data$NmPostPesq %<>% as.integer()
shp_gas_prices_hist@data$PcMedRev %<>% as.double()
shp_gas_prices_hist@data$PcDevRev %<>% as.double()
shp_gas_prices_hist@data$PcMinRev %<>% as.double()
shp_gas_prices_hist@data$PcMaxRev %<>% as.double()
shp_gas_prices_hist@data$PcMedDist %<>% as.double()
shp_gas_prices_hist@data$PcDevDist %<>% as.double()
shp_gas_prices_hist@data$PcMinDist %<>% as.double()
shp_gas_prices_hist@data$PcMaxDist %<>% as.double()
shp_gas_prices_hist@data$MgMedRev %<>% as.double()
shp_gas_prices_hist@data$MgMedDist %<>% as.double()
shp_gas_prices_hist@data$CfVarRev %<>% as.double()
shp_gas_prices_hist@data$CfVarDist %<>% as.double()
shp_gas_prices_hist@data$DtInicial %<>% as_date(format = '%Y-%m-%d', tz = "America/Sao_Paulo")
shp_gas_prices_hist@data$DtFinal %<>% as_date(format = '%Y-%m-%d', tz = "America/Sao_Paulo")

# prep gas_prices_historical ----

names(gas_prices_hist) <- plyr::mapvalues(names(gas_prices_hist), 
                                          gas_prices_hist_header$descricao, 
                                          gas_prices_hist_header$mnemonico, 
                                          warn_missing = FALSE)

# Adding PIB and POP Data

PIB_change <- select(pib, CodIBGE, Ano, PIBCorr, PIBPerCapCorr) %>%
  filter(Ano >= 2016) %>% 
  pivot_wider(values_fn = sum, names_from = Ano, values_from = c(PIBCorr, PIBPerCapCorr)) %>% 
  mutate(ChgPIB = PIBCorr_2017 / PIBCorr_2016 - 1,
         ChgPIBCap = PIBPerCapCorr_2017 / PIBPerCapCorr_2016 - 1)

PIB_change <-
  left_join(shp_gas_prices_hist@data, PIB_change, by = 'CodIBGE') %>%
  left_join(pop, by = 'CodIBGE') %>%
  select(c(CodIBGE, PIBCorr_2016, PIBCorr_2017, PIBPerCapCorr_2016, PIBPerCapCorr_2017, ChgPIB.x, ChgPIBCap.x, PopEstimada)) %>% as_tibble()

names(PIB_change) <- c("CodIBGE", "PIB_2016", "PIB_2017", "PIBCap2016", "PIBCap2017", "ChgPIB", "ChgPIBCap", "PopEst")

PIB_change$CodIBGE <- as.integer(PIB_change$CodIBGE)

1.6 Step 06: Salvamento dos datasets processados

Como último passo de preparação de dados, o dataset final é salvo nos formatos .rds e csv para uso nos demais relatórios, incluindo Power BI, e scripts.

# this step aims to save the prepared dataset ------

# delete intermediate datasets ----
rm(cities, master_cidade_estado, UFs)
invisible(gc)

# save datasets ----
write_rds(as_tibble(shp_gas_prices_hist@data), 'data/processed/gas_prices_hist.rds')
write_rds(as_tibble(shp_gas_prices_station@data), 'data/processed/gas_prices_station.rds')
write_rds(gas_prices_hist, 'data/processed/gas_prices_historical.rds')
write_rds(PIB_change, 'data/processed/pib_change.rds')

write_csv(as_tibble(shp_gas_prices_hist@data), 'data/processed/gas_prices_hist.csv')
write_csv(as_tibble(shp_gas_prices_station@data), 'data/processed/gas_prices_station.csv')
write_csv(gas_prices_hist, 'data/processed/gas_prices_historical.csv')
write_csv(PIB_change, 'data/processed/pib_change.csv')

writeOGR(obj = shp_gas_prices_hist, 
         dsn = 'data/processed/gas_prices_hist', 
         layer = 'gas_prices_hist', 
         driver = "ESRI Shapefile", 
         overwrite_layer = TRUE, 
         encoding = 'UTF-8')

writeOGR(obj = shp_gas_prices_station, 
         dsn = 'data/processed/gas_prices_station',
         layer = 'gas_prices_station', 
         driver = "ESRI Shapefile", 
         overwrite_layer = TRUE,
         encoding = 'UTF-8')

1.7 Step 07: Carregamento dos datasets

Este passo adicional, permite que os datasets já processados sejam carregados para o ambiente do R para uso e explorações via scripts.

# load datasets ----
gas_prices_hist           <- read_rds('./data/processed/gas_prices_hist.rds')
gas_prices_historical     <- read_rds('./data/processed/gas_prices_historical.rds')
gas_prices_station        <- read_rds('./data/processed/gas_prices_station.rds')
PIB_change                <- read_rds('./data/processed/pib_change.rds')


# load mnemônico ----

gas_prices_hist_header <- read_xlsx('./data/processed/mnemonico.xlsx', 
                                    sheet = 'gas_prices_hist')

gas_prices_station_header <- read_xlsx('./data/processed/mnemonico.xlsx', 
                                       sheet = 'gas_prices_station')

PIB_change_header <- read_xlsx('./data/processed/mnemonico.xlsx', 
                                       sheet = 'PIB_change')


# load_shape_files ----

shp_gas_prices_station <- readOGR('./data/processed/gas_prices_station/gas_prices_station.dbf',
                                  encoding = 'UTF-8',
                                  use_iconv = TRUE,
                                  stringsAsFactors = FALSE)

shp_gas_prices_hist <- readOGR('./data/processed/gas_prices_hist/gas_prices_hist.dbf',
                               encoding = 'UTF-8', 
                               use_iconv = TRUE, 
                               stringsAsFactors = FALSE)

2 Funções criadas

Para realização deste trabalho, algumas funções foram criadas para otimizar atividades e procedimentos repetitivos. Estas funções também podem, futuramente, serem reusadas em outros projetos ou mesmo serem adicionadas a uma library R.

# functions -------------------------------------------------------------------
ClearRStudioEnvironment <- function() {
  
  # clear environment and memory
  rm(list=ls())
  invisible(gc())
  
  # clear console screen
  cat("\014")
  
  # clear plots
  while (!is.null(dev.list()))  
    dev.off()
}

WriteLog <- function(TaskName, StartTime, EndTime, AdditionalInfo) {
  
  TotalTime <- difftime(EndTime, StartTime, tz, 
                        units = c("auto", "secs", "mins", "hours",
                                  "days", "weeks"))
  
  log  <- paste('[', Sys.time(), '] ',
                'Task: ', TaskName, ' | ', 
                'Time elapsed: ', TotalTime, ' | ',
                'Memory used: ', pryr::mem_used(), ' bytes | ',
                AdditionalInfo,
                sep = "")
  
  write(log, file = "log.txt", append = TRUE)
}