# Carregando o pacote
library(sf)
# Importando o shapefile
= st_read(dsn = "Bairros_Recife.shp") recife
7 Mapas
Nos dias atuais, é muito comum nos depararmos com dados georreferenciados. O crescimento de dados espaciais é relativamente recente. Porém, já experimentamos seus efeitos no dia a dia.
Visualizações de dados espaciais é fundamental para quem trabalha com análise de dados.
7.1 Shapefile
Se o intuito é representar o espaço de interesse, precisamos inicialmente discutir sobre o shapefile.
Um shapefile é um formato popular de arquivo contendo dados geoespaciais em forma de vetor usado por Sistemas de Informações Geográficas (SIG). Shapefiles espaciais descrevem geometrias: pontos, linhas e polígonos. Entre outras coisas, essas geometrias podem representar Poços, Rios, cidades, respectivamente.
O formato shapefile define a geometria e os atributos dos recursos referenciados geograficamente em três ou mais arquivos com extensões de arquivo específicas que devem ser armazenadas no mesmo espaço de trabalho do projeto. Eles são:
.shp - O arquivo principal que armazena a geometria do recurso, obrigatório,
.shx - O arquivo de índice que armazena o índice da geometria do recurso, obrigatório,
.dbf - A tabela do dBASE que armazena as informações de atributos dos recursos, obrigatório,
.prj, .sbn, .sbx, .fbn, .fbx, .ain, .aih, .atx, .ixs, .mxs, .xml, .cpg são outras extensões possíveis.
Alguns arquivos podem ser obtidos no site do IBGE (https://www.ibge.gov.br/geociencias/downloads-geociencias.html).
Acessem o site e sigam o seguinte caminho: Organização do territorio >> malhas territoriais. Vocês terão acesso:
malhas de setores censitários,
malhas municipais,
malhas do Brasil por município.
Atividade: Baixem o arquivo do Estado do Rio de Janeiro do ano de 2016 contendo os municípios. Vejam quantos arquivos foram baixados e quais suas extensões.
7.1.1 Importando Shapefile
Para importamos um shapefile para o R usaremos a função st_read
do pacote sf
.
A seguir, vamos apresentar os principais argumentos da função st_read
:
- dsn - o nome do arquivo a ser importado (com extensão .shp).
Linking to GEOS 3.11.0, GDAL 3.5.3, PROJ 9.1.0; sf_use_s2() is TRUE
Reading layer `Bairros_Recife' from data source
`/Users/jonyarrais/Documents/VisualizacaoDados/Bases/Cap7/Bairros_Recife.shp'
using driver `ESRI Shapefile'
Simple feature collection with 94 features and 10 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 277547.5 ymin: 9098032 xmax: 295287.7 ymax: 9123296
Projected CRS: SIRGAS 2000 / UTM zone 25S
Para plotarmos o shape, vamos inicialmemte recorrer ao ggplot2
.
# Carregando o pacote
library(ggplot2)
library(dplyr)
Attaching package: 'dplyr'
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
## Para plotar somente o contorno do objeto recife
ggplot(data = recife) +
geom_sf(fill = "White")
# Selecionando o shape do bairro de Boa Viagem
= recife |>
Boa_viagem filter(EBAIRRNOME == "BOA VIAGEM")
# Visualizando o objeto Boa_viagem
Boa_viagem
Simple feature collection with 1 feature and 10 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 288679.6 ymin: 9098032 xmax: 292546.5 ymax: 9104302
Projected CRS: SIRGAS 2000 / UTM zone 25S
CBAIRRCODI VBAIRROID EBAIRRNOME CRPAAACODI CMICROCODI TBAIRRULAT CEMPRECODI
1 205 0 BOA VIAGEM 6 1 1899-12-30 0
AUSUACMATR EBAIRRNO_1 EBAIRRLINK geometry
1 0 Boa Viagem <NA> MULTIPOLYGON (((289794.1 90...
# Plotando o shape de Boa Viagem
ggplot(data = Boa_viagem) +
geom_sf() +
theme_light()
# Unindo poligonos no shapefile
= recife |>
novo_recife group_by(CRPAAACODI) |>
summarize(n = n())
# Visualizando o novo objeto
novo_recife
Simple feature collection with 6 features and 2 fields
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: 277547.5 ymin: 9098032 xmax: 295287.7 ymax: 9123296
Projected CRS: SIRGAS 2000 / UTM zone 25S
# A tibble: 6 × 3
CRPAAACODI n geometry
<dbl> <int> <POLYGON [m]>
1 1 11 ((291904.5 9106181, 291809.5 9106087, 291804.2 9106082, 2916…
2 2 18 ((290782.8 9111147, 290674.9 9111202, 290670.2 9111204, 2906…
3 3 29 ((288186.9 9110691, 288112.3 9110726, 288077.5 9110745, 2880…
4 4 12 ((287295.9 9108372, 287294 9108364, 287288.6 9108349, 287228…
5 5 16 ((287565.4 9103874, 287544.5 9103870, 287505.3 9103870, 2874…
6 6 8 ((292546.5 9104121, 292509.4 9104020, 292477.6 9103925, 2924…
# Plotando o novo objeto
ggplot(data = novo_recife) +
geom_sf(fill = "White") +
theme_light()
Determinados shapifiles podem ser porduzidos com uma quantidade muito grande de pontos para definir os contornos da região de interesse. Nestes casos, os mapas que serão plotados serão pesados e provavelmente demoram a carregar. Existe uma forma de deixar esses arquivos mais leves nestes cenários.
# Carregando o pacote
library(rmapshaper)
The legacy packages maptools, rgdal, and rgeos, underpinning the sp package,
which was just loaded, will retire in October 2023.
Please refer to R-spatial evolution reports for details, especially
https://r-spatial.org/r/2023/05/15/evolution4.html.
It may be desirable to make the sf package available;
package maintainers should consider adding sf to Suggests:.
The sp package is now running under evolution status 2
(status 2 uses the sf package in place of rgdal)
# Simplificando o shape
= ms_simplify(input = recife,
Recife_simples keep = 0.1,
keep_shapes = TRUE)
O argumento input
é o shape a ser simplificado, o keep
é a proporção dos pontos que você deseja manter e o keep_shapes = TRUE
impede que características pequenas dos polígonos sumam, no caso de uma grande simplificação.
# Plotando o objeto simplificado
ggplot(data = Recife_simples) +
geom_sf(fill = "White") +
theme_light()
7.2 Mapa de pontos
Quando possuímos as coordenadas (lat/long) da ocorrência de um evento de interesse, uma visualização apropriada é a criação de um mapa de pontos. Neste mapa é possível avaliar a existência de aglomerações dos pontos em algumas localidades da região de interesse.
Atividade: Criem um projeto chamado MapaNY. Importem o arquivo nyshape.shp e armazenem em um objeto chamado NYShp.
Reading layer `nyshape' from data source
`/Users/jonyarrais/Documents/VisualizacaoDados/Bases/Cap7/nyshape.shp'
using driver `ESRI Shapefile'
Simple feature collection with 71 features and 3 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -74.25559 ymin: 40.49612 xmax: -73.70001 ymax: 40.91553
Geodetic CRS: WGS84(DD)
# Visualizando o objeto
NYShp
Simple feature collection with 71 features and 3 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -74.25559 ymin: 40.49612 xmax: -73.70001 ymax: 40.91553
Geodetic CRS: WGS84(DD)
First 10 features:
shape_leng boro_cd shape_area geometry
1 51549.56 311 103177785 MULTIPOLYGON (((-73.97299 4...
2 65821.88 313 88195686 MULTIPOLYGON (((-73.98372 4...
3 52245.83 312 99525500 MULTIPOLYGON (((-73.9714 40...
4 37008.10 304 56663217 MULTIPOLYGON (((-73.89647 4...
5 62239.83 209 114266297 MULTIPOLYGON (((-73.83979 4...
6 83998.36 212 154896607 MULTIPOLYGON (((-73.79386 4...
7 35875.71 206 42664311 MULTIPOLYGON (((-73.87185 4...
8 47817.46 208 92071724 MULTIPOLYGON (((-73.89663 4...
9 32820.40 226 50566411 MULTIPOLYGON (((-73.8679 40...
10 43326.85 317 93810207 MULTIPOLYGON (((-73.90755 4...
Atividade: Importem o arquivo NYPD.csv e armazenem em um objeto chamado NYPD.
O arquivo contém dados sobre crimes ocorridos na cidade de Nova York. Entre as variáveis disponibilizadas, podemos citar o tipo do crime (TYPE), as coordenadas (latitude e longitude), entre outras.
# Visualizando o objeto
NYPD
# A tibble: 407 × 6
LAW_CAT_CD TYPE BORO_NM Day Longitude Latitude
<chr> <chr> <chr> <dbl> <dbl> <dbl>
1 FELONY VANDALISM QUEENS 1 -73.7 40.7
2 FELONY ROBBERY BRONX 1 -73.9 40.9
3 FELONY ROBBERY QUEENS 3 -73.8 40.7
4 FELONY ROBBERY BROOKLYN 4 -74.0 40.7
5 FELONY ROBBERY QUEENS 2 -73.8 40.7
6 FELONY VANDALISM QUEENS 5 -73.8 40.7
7 FELONY ROBBERY STATEN ISLAND 6 -74.2 40.6
8 FELONY ROBBERY QUEENS 3 -73.7 40.7
9 FELONY ROBBERY BRONX 2 -73.9 40.9
10 FELONY MURDER QUEENS 3 -73.8 40.7
# ℹ 397 more rows
Vamos fazer o mapa de pontos dos crimes na cidade de Nova York usando o ggplot2
.
#Plotando as localizações dos delitos
ggplot(data = NYShp) +
geom_sf(fill = "White") +
geom_point(data = NYPD,
mapping = aes(x = Longitude,
y = Latitude),
colour = 'Dark Blue') +
theme_light()
Vale ressaltar que o data
indicado na função ggplot
é o shape, já no geom_point
foi preciso especificar um data
diferente, a base de dados.
Ë possível criar mapas de pontos indicando os diferentes tipos de crime, por exemplo.
# Mapa de pontos indicando o tipo de crime com o ggplot2
= ggplot(data = NYShp) +
mapa1 geom_sf(fill = "White") +
geom_point(data = NYPD,
aes(x = Longitude,
y = Latitude,
colour = TYPE),
size = 0.8) +
theme_light()
mapa1
Atividade: Com base no conteúdo da disciplina visto até o momento, crie o código necessário para reproduzir a visualização abaixo.
7.3 Mapa coroplético
Mapas coropléticos são usados em cenários no qual a variável de interesse foi observada de forma agregada para alguma partição em áreas do espaço de interesse. Por exemplo, suponha que foram observados o número de roubos de carros nos bairros da cidade do Rio de Janeiro. Neste cenário, a região de interesse é o Rio de Janeiro, que está particionada em seus bairros e a variável foi observada de forma agregada paea cada área.
Atividade: Importe o arquivo Vendas_agregada_bairro.csv e guarde em um objeto chamado base_venda.
A base fornece o registro do número de produtos vendidos (por semestre e no ano todo) por bairro de um determinado produto, entre outras.
Rows: 94 Columns: 6
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (1): no_bairro_residencia
dbl (5): num.vendas.1sem, num.vendas.2sem, num.vendas, gasto, porc_panfletagem
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#Visualinado a base de dados
base_venda
# A tibble: 94 × 6
no_bairro_residencia num.vendas.1sem num.vendas.2sem num.vendas gasto
<chr> <dbl> <dbl> <dbl> <dbl>
1 PAU FERRO 1 0 1 4460
2 SANTO ANTONIO 6 2 8 4590
3 PAISSANDU 11 4 15 4369
4 ILHA DO LEITE 18 1 19 4614
5 SOLEDADE 1 20 21 4788
6 JAQUEIRA 20 4 24 4652
7 TORREAO 3 27 30 4794
8 CABANGA 6 25 31 4647
9 SANTANA 12 21 33 4852
10 DERBY 20 14 34 4832
# ℹ 84 more rows
# ℹ 1 more variable: porc_panfletagem <dbl>
Para criarmos um mapa coropléticos precisamos inicialmente acrescentar a variável de interesse ao shape. Faremos isso, fazendo um merge da base com o shape. Neste caso, usamos o left_join
passando como base inicial o shape, para garantir que a base que será retornada terá exatamente as linhas que já existem no shape e usamos os nomes dos bairros para fazer a junção.
#Fazendo a relacao dos dois data frames
= left_join(x = recife,
recife y = base_venda,
by = c("EBAIRRNOME" = "no_bairro_residencia"))
# Visualizando o objeto
recife
Simple feature collection with 94 features and 15 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 277547.5 ymin: 9098032 xmax: 295287.7 ymax: 9123296
Projected CRS: SIRGAS 2000 / UTM zone 25S
First 10 features:
CBAIRRCODI VBAIRROID EBAIRRNOME CRPAAACODI CMICROCODI TBAIRRULAT
1 19 0 RECIFE 1 1 1899-12-30
2 27 0 SANTO ANTONIO 1 2 1899-12-30
3 35 0 SAO JOSE 1 2 1899-12-30
4 43 0 ILHA JOANA BEZERRA 1 3 1899-12-30
5 51 0 CABANGA 1 2 1899-12-30
6 60 0 COELHOS 1 3 1899-12-30
7 78 0 ILHA DO LEITE 1 2 1899-12-30
8 86 0 BOA VISTA 1 2 1899-12-30
9 94 0 PAISSANDU 1 2 1899-12-30
10 108 0 SANTO AMARO 1 1 1899-12-30
CEMPRECODI AUSUACMATR EBAIRRNO_1 EBAIRRLINK num.vendas.1sem
1 0 0 Recife <NA> 39
2 0 0 Santo Antônio <NA> 6
3 0 0 São José <NA> 163
4 0 0 Ilha Joana Bezerra <NA> 187
5 0 0 Cabanga <NA> 6
6 0 0 Coelhos <NA> 123
7 0 0 Ilha do Leite <NA> 18
8 0 0 Boa Vista <NA> 98
9 0 0 Paissandú <NA> 11
10 0 0 Santo Amaro <NA> 495
num.vendas.2sem num.vendas gasto porc_panfletagem
1 42 81 4811 0.7075714
2 2 8 4590 0.1632857
3 58 221 4980 0.7220000
4 271 458 5082 0.7294286
5 25 31 4647 0.2832857
6 157 280 5022 0.7262857
7 1 19 4614 0.2788571
8 117 215 4988 0.7181429
9 4 15 4369 0.1738571
10 274 769 5208 0.9671429
geometry
1 MULTIPOLYGON (((294617.4 91...
2 MULTIPOLYGON (((293353.3 91...
3 MULTIPOLYGON (((292458 9107...
4 MULTIPOLYGON (((290464.9 91...
5 MULTIPOLYGON (((291566 9106...
6 MULTIPOLYGON (((291634.3 91...
7 MULTIPOLYGON (((291634.2 91...
8 MULTIPOLYGON (((291721.3 91...
9 MULTIPOLYGON (((291140.4 91...
10 MULTIPOLYGON (((294038.3 91...
A seguir, apresentamos o mapa coroplético do número de produtos vendidos no ano.
#Mapa coropletico do numero de vendas de produto
ggplot(data = recife,
mapping = aes(fill = num.vendas)) +
geom_sf()
Como alterar características deste gráfico?
#Modificando o mapa coropletico
ggplot(data = recife,
mapping = aes(fill = num.vendas)) +
geom_sf() +
scale_fill_gradient(name = "Vendas",
low = "White",
high = "Red") +
theme_light() +
theme(legend.title = element_text(size = 16,
colour = "Red",
face = "bold"),
legend.text = element_text(size = 10,
colour = "Red"))
O pacote tmap
é outro pacote bastante útil para a criação de mapas coropléticos.
#Carregando pacote tmap
library(tmap)
#Construindo o mapa coropletico para vendas
tm_shape(shp = recife) +
tm_fill(col = "num.vendas",
palette = "Greens",
title = "Vendas")
## tm_shape - cria um elemento tmap que especifica um objeto espacial
## tm_fill - cria um elemento tmap que desenha e preenche o mapa
#Argumentos:
#shp - um objeto da classe sf
#col - a variavel/atributo que deseja plotar
#palette - a paleta de cores
#title - Nome que deseja mostrar no titulo da legenda
#Transformando em uma geometria valida
= st_make_valid(x = recife)
recife
## st_make_valid - transforma uma geometria invalida em uma valida
#Argumentos:
#x - um objeto da classe sf
#Modificando o numero de intervalos
tm_shape(shp = recife) +
tm_fill(col = "num.vendas",
n = 4,
palette = "Greens",
title = "Vendas")
#Definindo os limites e o numero de intervalos
= tm_shape(shp = recife) +
mapa tm_fill(col = "num.vendas",
breaks = quantile(recife$num.vendas, probs = seq(0,1,.1)),
palette = "Greens",
title = "Vendas") +
tm_borders(lwd = 0.75,
lty = "solid")
## tm_borders - desenha as bordas que separam os poligonos
#Argumentos:
#lwd - espessura da borda
#lty - tipo de linha
#Visualizando o mapa
mapa
#Mudando o estilo do mapa com tm_style (pre-definido)
+
mapa tm_style("cobalt")
#Mudando o estilo do mapa com tm_layout (criar)
+
mapa tm_layout(title = "2018",
legend.outside = TRUE,
legend.text.color = "Dark Green")
## tm_layout - especifica configuracoes para o layout do mapa
#Argumentos:
#title - um titulo acima da legenda
#legend.outside - para a legenda aparecer ao lado de fora do mapa
#legend.text.color - cor da legenda
#Incluindo texto nos mapas
+
mapa tm_text(text = "EBAIRRNOME",
size = "num.vendas",
legend.size.show = FALSE) +
tm_layout(legend.outside = TRUE)
## tm_text - especifica nomes para os poligonos
#Argumentos:
#text - variavel que deseja aparecer como texto nos poligonos
#size - numero ou uma variavel que vai determinar o tamanho da fonte
#legend.size.show - se deseja apresentar a legenda para os diferentes tamanhos da letra
#Grafico para mais de uma variavel
tm_shape(shp = recife) +
tm_fill(col = c("num.vendas.1sem","num.vendas.2sem"),
title = c("1 Sem", "2 Sem"),
palette = "Reds") +
tm_facets(nrow = 1) +
tm_borders() +
tm_layout(legend.position = c("left","bottom"))
#Colocando todos os graficos em uma mesma escala
tm_shape(shp = recife) +
tm_fill(col = c("num.vendas.1sem","num.vendas.2sem"),
title = "Vendas",
palette = "Reds") +
tm_facets(nrow = 1,
free.scales = FALSE) +
tm_borders() +
tm_layout(panel.labels = c("1 Sem","2 Sem"))
7.3.1 Mapas interativos com o tmap
No tmap, é possível contruir mapas interativos usando a função tmap_mode
com argumento view. Todos os mapas criados após definirmos tmap_mode("view")
serão mapas interativos. Para voltarmos a criar mapas estáticos é preciso definir tmap_mode("plot")
.
#Definindo o tipo do mapa como interativo
tmap_mode("view")
tm_shape(shp = recife) +
tm_fill(col = "num.vendas",
breaks = quantile(recife$num.vendas, probs = seq(0,1,.2)),
palette = "Greens",
title = "Vendas")
No botão, do lado esquerdo, é possível mudar o mapa do fundo.
Ao passar o mouse sobre os bairros serão apresentados os valores da variável. Para melhorar a visualização, vamos criar uma variável que apresenta o nome do bairro e o valor de produtos vendidos para que ao passarmos o mouse sobre os bairros seja exibido o nome e o valor da venda.
#Ativando pacote
library(stringr)
#Melhorando o grafico
= recife |>
recife mutate(nome_casos = str_c(EBAIRRNOME, " - ", num.vendas))
tm_shape(shp = recife) +
tm_fill(col = "num.vendas",
breaks = quantile(recife$num.vendas, probs = seq(0,1,.2)),
palette = "Greens",
title = "Vendas",
id = "nome_casos")