Este projeto é inspirado na live intitulada “Geomarketing na prática” feita por Daniel Andrade no dia 25/01/2023.
Os dados fictícios foram fornecidos durante a live. É um estudo que busca identificar onde estão localizados os potenciais clientes de uma pizzaria no município do Rio de Janeiro.
Alguns desafios são apresentados durante o desenvolvimento do estudo, como trabalhar com diferentes formatos de arquivos. Aqui utilizei as extensões .csv, .gpkg, .shp e .kml.
Além disso, esse projeto é uma maneira de me desafiar. Enquanto o Daniel desenvolveu a análise utilizando o QGIS, eu busquei adaptar a mesma lógica dele, mas utilizando o R. Também procurei otimizar algumas etapas, principalmente no tratamento das planilhas.
Você pode optar por exibir ou ocultar todos os códigos utilizados através do menu superior Code.
pacman::p_load(
# ETL (extract, transform, load)
janitor, readr, readxl, lubridate,
dplyr,
tidyverse,
glue,
skimr,
# Visualização
ggplot2,
rmarkdown,
knitr,
kableExtra,
ggthemes,
ggtext
)pacman::p_load(
sf, raster,
leaflet, leaflet.extras,
rgdal, rgeos,
maps,
mapview,
ggmap
)No code chunk abaixo estou realizando a seguinte sequência de passos (pipeline):
Importo o arquivo .csv.
Coloco o nome das colunas em letras minúsculas e sem espaço/caracteres especiais para facilitar a manipulação.
Gero duas novas colunas:
A coluna endereco_completo será usada para a geocodificação.
A coluna Name será usada para unificar os dados (inner_join()) já geocodificados com as demais informações de endereço.
Reordeno as colunas, para facilitar a visualização
E, por fim, altero o formato da coluna para tibble, para ser melhor utilizada no R.
clientes_pizzaria <- read.csv(
"E:/Desktop/Banco de dados - Super Live/Clientes _Pizzaria_RJ.csv",
header = TRUE,
sep = ";",
) %>%
janitor::clean_names() %>%
mutate(
endereco_completo = paste0(endereco, ", ", numero, ", ", bairro, "-", cidade),
Name = endereco,
) %>%
rename(
id_cliente = cliente ,
) %>%
dplyr::select(
c(1:3),
Name,
endereco_completo,
everything()
) %>%
as_tibble()No code chunk abaixo importo o arquivo em formato .gpkg da pizzaria. Além disso, transformo para o SRC SIRGAS2000.
pizzaria_RJ <- st_read(
"E:/Desktop/Banco de dados - Super Live/Pizzaria.gpkg"
) %>%
st_transform(crs = 4674) #4326 = WGS84, 4674 = SIRGAS2000FALSE Reading layer `escola_tcnica' from data source
FALSE `E:\Desktop\Banco de dados - Super Live\Pizzaria.gpkg' using driver `GPKG'
FALSE Simple feature collection with 1 feature and 1 field
FALSE Geometry type: POINT
FALSE Dimension: XY
FALSE Bounding box: xmin: 683707.2 ymin: 7464771 xmax: 683707.2 ymax: 7464771
FALSE Projected CRS: SIRGAS 2000 / UTM zone 23S
Após fazer o download dos dados do site do IBGE1
lim_mun_RJ <- shapefile(
"E:/Desktop/Banco de dados - Super Live/RJ_Municipios_2021.shp"
) %>%
as("sf")
lim_mun_RJ %>%
head(5)## Simple feature collection with 5 features and 4 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -44.64034 ymin: -23.22766 xmax: -41.78408 ymax: -21.60125
## CRS: +proj=longlat +ellps=GRS80 +no_defs
## CD_MUN NM_MUN SIGLA AREA_KM2 geometry
## 1 3300100 Angra dos Reis RJ 813.420 MULTIPOLYGON (((-44.14994 -...
## 2 3300159 Aperibé RJ 94.542 MULTIPOLYGON (((-42.12536 -...
## 3 3300209 Araruama RJ 638.276 MULTIPOLYGON (((-42.18387 -...
## 4 3300225 Areal RJ 110.724 MULTIPOLYGON (((-43.03716 -...
## 5 3300233 Armação dos Búzios RJ 70.977 MULTIPOLYGON (((-41.91817 -...
Nesta etapa verifico a estrutura do dado: como estão ordenadas as colunas, qual o conteúdo delas, o número de observações totais (ou n) e se temos valores não medidos/faltantes (NA).
Abaixo, temos a visualização da planilha clientes_pizzaria.
Encontramos que temos 46 linhas e 10 colunas.
clientes_pizzaria %>%
str()## tibble [46 × 10] (S3: tbl_df/tbl/data.frame)
## $ id_cliente : int [1:46] 1 2 3 5 6 7 8 9 10 11 ...
## $ endereco : chr [1:46] "Rua Isabel Alves" "Rua Franca Júnior" "Rua Bocaiúva Cunha" "Rua Sotero dos Reis" ...
## $ numero : chr [1:46] "28" "361" "48" "107" ...
## $ Name : chr [1:46] "Rua Isabel Alves" "Rua Franca Júnior" "Rua Bocaiúva Cunha" "Rua Sotero dos Reis" ...
## $ endereco_completo: chr [1:46] "Rua Isabel Alves, 28, Taquara-Rio de Janeiro" "Rua Franca Júnior, 361, Andaraí-Rio de Janeiro" "Rua Bocaiúva Cunha, 48, Gardênia Azul-Rio de Janeiro" "Rua Sotero dos Reis, 107, Praça da Bandeira-Rio de Janeiro" ...
## $ bairro : chr [1:46] "Taquara" "Andaraí" "Gardênia Azul" "Praça da Bandeira" ...
## $ cidade : chr [1:46] "Rio de Janeiro" "Rio de Janeiro" "Rio de Janeiro" "Rio de Janeiro" ...
## $ uf : chr [1:46] "RJ" "RJ" "RJ" "RJ" ...
## $ pais : chr [1:46] "Brasil" "Brasil" "Brasil" "Brasil" ...
## $ cep : int [1:46] 22723010 20510270 22765529 20270200 20211070 20250001 22723010 20261005 20760070 20270133 ...
clientes_pizzaria %>%
skim() | Name | Piped data |
| Number of rows | 46 |
| Number of columns | 10 |
| _______________________ | |
| Column type frequency: | |
| character | 8 |
| numeric | 2 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| endereco | 0 | 1 | 10 | 26 | 0 | 39 | 0 |
| numero | 0 | 1 | 2 | 4 | 0 | 39 | 0 |
| Name | 0 | 1 | 10 | 26 | 0 | 39 | 0 |
| endereco_completo | 0 | 1 | 39 | 60 | 0 | 43 | 0 |
| bairro | 0 | 1 | 4 | 17 | 0 | 26 | 0 |
| cidade | 0 | 1 | 11 | 18 | 0 | 4 | 0 |
| uf | 0 | 1 | 2 | 2 | 0 | 1 | 0 |
| pais | 0 | 1 | 6 | 6 | 0 | 1 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| id_cliente | 0 | 1 | 26.63 | 15.38 | 1 | 13.5 | 26.5 | 38.75 | 54 | ▇▇▇▇▆ |
| cep | 0 | 1 | 21258477.07 | 1389354.92 | 20211070 | 20260030.0 | 20526350.0 | 22340295.75 | 25561120 | ▇▁▂▁▁ |
No code chunk abaixo, armazeno as informações da função skim() em formato tibble na variável eda, para a manipulação de dados dentro do R. Na sequência, identificamos as colunas geradas a partir da função skim().
eda <- clientes_pizzaria %>%
skim() %>%
as_tibble()eda %>%
names()| value |
|---|
| skim_type |
| skim_variable |
| n_missing |
| complete_rate |
| character.min |
| character.max |
| character.empty |
| character.n_unique |
| character.whitespace |
| numeric.mean |
| numeric.sd |
| numeric.p0 |
| numeric.p25 |
| numeric.p50 |
| numeric.p75 |
| numeric.p100 |
| numeric.hist |
Existem 8 colunas do tipo character e 2 colunas do tipo numeric.
eda %>%
count(skim_type)## # A tibble: 2 × 2
## skim_type n
## <chr> <int>
## 1 character 8
## 2 numeric 2
No code chunk abaixo identificamos há diferença no número de endereços e endereços completos, ou seja, temos valores repetidos na coluna endereco. Isso aponta para o fato de termos múltiplos clientes na mesma rua.
eda %>%
dplyr::select(
skim_variable,
character.n_unique
)## # A tibble: 10 × 2
## skim_variable character.n_unique
## <chr> <int>
## 1 endereco 39
## 2 numero 39
## 3 Name 39
## 4 endereco_completo 43
## 5 bairro 26
## 6 cidade 4
## 7 uf 1
## 8 pais 1
## 9 id_cliente NA
## 10 cep NA
Há 0 valores faltantes.
eda %>%
dplyr::select(n_missing) %>%
sum()## [1] 0
eda_rua <- clientes_pizzaria %>%
distinct(
endereco_completo,
.keep_all = TRUE
) %>%
dplyr::select(
endereco, numero, endereco_completo, bairro,
) %>%
group_by(endereco) %>%
mutate(n = n()) %>%
ungroup() %>%
arrange(
desc(n),
desc(bairro),
desc(endereco),
numero
) %>%
dplyr::select(
# -endereco,
-numero,
)| endereco | endereco_completo | bairro | n |
|---|---|---|---|
| Rua Santa Amélia | Rua Santa Amélia, 13, Praça da Bandeira-Rio de Janeiro | Praça da Bandeira | 3 |
| Rua Santa Amélia | Rua Santa Amélia, 88, Praça da Bandeira-Rio de Janeiro | Praça da Bandeira | 3 |
| Rua Santa Amélia | Rua Santa Amélia, 881, Praça da Bandeira-Rio de Janeiro | Praça da Bandeira | 3 |
| Rua Senador Nabuco | Rua Senador Nabuco, 23, Vila Isabel-Rio de Janeiro | Vila Isabel | 2 |
| Rua Senador Nabuco | Rua Senador Nabuco, 461, Vila Isabel-Rio de Janeiro | Vila Isabel | 2 |
| Rua Barão de Itapagipe | Rua Barão de Itapagipe, 254, Rio Comprido-Rio de Janeiro | Rio Comprido | 2 |
| Rua Barão de Itapagipe | Rua Barão de Itapagipe, 71, Rio Comprido-Rio de Janeiro | Rio Comprido | 2 |
| Rua Barra do Pirai | Rua Barra do Pirai, 75, Vilar dos Teles-São João de Meriti | Vilar dos Teles | 1 |
| Rua Sambaitiba | Rua Sambaitiba, 43, Vila Rosário-Duque de Caxias | Vila Rosário | 1 |
| Rua Padre Artola | Rua Padre Artola, 11, Vidigal-Rio de Janeiro | Vidigal | 1 |
No code chunk acima identificamos onde há mais clientes no mesmo bairro. Através da variável eda_rua percebemos que algumas ruas se repetem. A Rua Santa Amélia, do bairro Praça da Bandeira, é a que possui maior número de observações, com n total igual a 3.
Brasil <- getData(
"GADM",
country = "Brazil",
level = 3
) %>%
st_as_sf()
RJ <- subset(Brasil,
NAME_1 == "Rio de Janeiro")
# Definindo o SRC
RJ <- RJ %>%
st_transform(crs = 4674) #4326 = WGS84, 4674 = SIRGAS2000
clientes_pizzaria %>%
ggplot()+
geom_sf(
data = RJ
)+
labs(
title = "Municípios - RJ",
x = "Longitude",
y = "Latitude",
caption = "Elaborado por: Leonardo Fernandes Wink\n26/01/2023"
)+
theme_bw()+
theme(
plot.title = element_text(
size = 16,
hjust = 0.5,
color = "black",
face = "bold"
),
)Figure 5.1: Mapa estático dos municípios do Rio de Janeiro
Google Earth Pro e salve em .kml.code chunk são gerados os campos de lat e long.clientes_coords_attr <- read_sf(
"E:/Desktop/Banco de dados - Super Live/Clientes _Pizzaria_RJ.kml"
) %>%
st_zm(
drop = TRUE,
what = "ZM"
) clientes_coords_attr <- clientes_coords_attr %>%
dplyr::mutate(long = sf::st_coordinates(.)[,1],
lat = sf::st_coordinates(.)[,2]) %>%
st_transform(crs = 4674) #4326 = WGS84, 4674 = SIRGAS2000clientes_pizzaria_join <- inner_join(
x = clientes_pizzaria,
y = clientes_coords_attr,
by = "Name"
)Nesta seção geramos os mapas interativos. Você pode dar zoom, arrastar para os lados e clicar nos pontos para saber mais informações a respeito.
Gerando o mapa que será base para os demais.
Especificando o zoom inicial;
Adicionando a quadrícula dos graus (intervalo de 5º em 5º);
Definindo o provedor do mapa-base;
Se é imagem de satélite (ESRI) ou
Software livre, o Open Street Map (OSM)
Adicionando o limite dos municípios do estado do Rio de Janeiro;
Adicionando a barra de escala no canto inferior direito.
mapa_interativo <- clientes_pizzaria_join %>%
leaflet() %>%
setView(
lat = -23,
lng = -43.2,
zoom = 8
) %>%
addSimpleGraticule(
interval = 5,
showOriginLabel = FALSE,
) %>%
addProviderTiles(
# "Esri.WorldImagery" #Imagem de satélite
"OpenStreetMap.Mapnik" #OpenStreetMap -> Software livre
) %>%
addPolygons(
data = lim_mun_RJ,
color = "red",
fill = FALSE,
weight = 2.5,
opacity = 1,
) %>%
addScaleBar(
# map,
position = "bottomright",
options = scaleBarOptions(
maxWidth = 150,
metric = TRUE,
imperial = FALSE,
updateWhenIdle = TRUE
)
)A partir das áreas de influência, depreende-se a área em que devem ser direcionadas campanhas de marketing, conforme a figura 6.1.
mapa_interativo %>%
addCircles(
data = pizzaria_RJ,
radius = 3000,
fillOpacity = 0.1,
color = "green",
popup = ~paste0(
"<b>Endereço: </b>", "Rua João Paulo I", ", ", "s/n", "<br>",
"<b>Bairro: </b>", "Estácio", "<br>",
"<b>Município: </b>", "Rio de Janeiro", "<br>",
"<b>CEP: </b>", "-", "<br>",
"<b>Área de Influência: </b>", "3km",
sep = " "
)
) %>%
addCircles(
data = pizzaria_RJ,
radius = 1000,
fillOpacity = 0.3,
color = "green",
popup = ~paste0(
"<b>Endereço: </b>", "Rua João Paulo I", ", ", "s/n", "<br>",
"<b>Bairro: </b>", "Estácio", "<br>",
"<b>Município: </b>", "Rio de Janeiro", "<br>",
"<b>CEP: </b>", "-", "<br>",
"<b>Área de Influência: </b>", "1km",
sep = " "
)
) %>%
addCircleMarkers(
data = clientes_pizzaria_join,
lng = ~long,
lat = ~lat,
radius = 5,
fillOpacity = 0.6,
color = "orange",
popup = ~paste0(
"<b>Endereço: </b>", {endereco}, ", ", numero, "<br>",
"<b>Bairro: </b>", bairro, "<br>",
"<b>Município: </b>", cidade, "<br>",
"<b>CEP: </b>", cep, "<br>",
sep = " "
)
) %>%
addCircleMarkers(
data = pizzaria_RJ,
radius = 8,
fillOpacity = 1,
color = "green",
popup = ~paste0(
"<b>Endereço: </b>", "Rua João Paulo I", ", ", "s/n", "<br>",
"<b>Bairro: </b>", "Estácio", "<br>",
"<b>Município: </b>", "Rio de Janeiro", "<br>",
"<b>CEP: </b>", "-", "<br>",
sep = " "
)
)