Está en la página 1de 23

Guía para Mapas en R

Mauricio_Mardones_I

1
Guia para elaborar mapas de uso
La motivación de este documento es mostrar algunas formas simples de visualizar datos georeferenciados y
alguna variable de interés en el espacio, lo que generalmente en nuestro departamento es común, ploteando
datos como captura, esfuerzo, CPUE, long medias, etc. Por otro lado, aquí también podremos evaluar la
distribución de nuestras variables en una escala temporal, ya sea en días, meses y/o años.El objetivo es poder
visualizar de forma rapida y simple datos en el espacio, ya que eso nos puede dar algunas señales de como es
la dínamica de poblaciones del recurso que estamos analizando.
La idea es aprovechar R y todas sus propiedades gráficas, que gracias a las nuevas librerias, ha competido de
buena forma con el reinado (hasta ahora) de otras plataformas GIS; como ArcMap, Surfer, Matlab,etc., R
ahora (por lo poco que conozco) cuenta con prestaciones cartográficas múltiples y suficiente (útil) resolución.
En terminos de estética de mapas, esta es tan diversa como personas en el mundo, por lo que es muy probable,
esta guía no cumpla a cabalidad el gusto, pero cada uno puede luego customizar a su gusto el code.
En este caso, mostraremos 3 maneras de hacer mapas en R de forma muy sencilla.
1. Leyendo shapes files.
2. Usando marmpap library.
3. Generando un raster.

2
Librerías y datos
Lo primero es cargar todas las librerias necesarias para hacer mapas
library(RColorBrewer) #para hacer paletas de colores
library(viridis) # Mas colres
library(rgdal) #para leer shapes
library(ggplot2) #para todo
library(maptools)
library(sf) # parte de transformaciones de coordenadas
library(tidyverse) # Todo, incluso mas que Rstudio mismo!
library(patchwork) # para juntar ggplot
library(marmap) # para sacar batimetrias
library(mapproj) #no recuerdo
library(maps) # para obtener limites
library(ggspatial) #para figuritas
library(raster) #para extraer bordes
#library(ggmap) # estos son mapas mas estilo pagina web. Hay que tener un key. No lo usaré.

Ahora leo el directorio y los archivos necesarios. Aqui he alojado una base de datos que es la que generalmente
tenemos. En este caso datos georeferenciados de capturas de erizo del sur.
rm(list=ls())
setwd("C:/Users/mauricio.mardones/Documents/IFOP/Maps_R/Maps_2")
point <- read.csv2("geo_erizo_1996_2019.csv", sep=",",
stringsAsFactors=FALSE, na.strings = T)

Es importante senalar que todos los ejercicios entan hechos en sistema de coordenadas geograficos (Lat, Long).
Para tener una idea de como vienen los datos de este ejemplo.
Para tener una idea de como deben verse los datos crudos, leo los 10 primeros datos y algunas variables de
interés. En este caso, lat Long y Capturas.
head(point [c(3, 4, 8, 15 )], 10)

## LATITUD LONGITUD ANO_REG CAPTURA_2


## 1 -43.947778 -74.030672 2015 1451
## 2 -43.947778 -74.030672 2015 779
## 3 -43.947778 -74.030672 2016 606
## 4 -43.947778 -74.030672 2015 810
## 5 -43.947778 -74.030672 2016 1064
## 6 -43.947778 -74.030672 2015 896
## 7 -43.947778 -74.030672 2015 461
## 8 -43.947778 -74.030672 2016 1034
## 9 -43.947778 -74.030672 2015 1029
## 10 -43.947778 -74.030672 2015 878
Luego una transfomación de la estructura de ciertos datos para no tener problemas en la manipulación
respecto al formato de cada uno.
#estrucutura de los datos
estr <- glimpse(point)

Ahora cambio a numeric las variables que no soportan los mapas


Saco los datos cero en coordenadas y en mi caso cambió de kilos a toneladas para no tener numeros tan
grandes, en este caso, capturas.

3
point <- filter(point, LONGITUD < 0) %>%
mutate(CAPT = CAPTURA_2/1000)

A su vez, pueden probar con algunos datos que tengan estas estructura
point <- data.frame(long=c(-172,-173,-170,-170.5,-170.52),
lat=c(62.1,62.2,62.3,63,65),
capt=c(150, 100, 40, 590, 320))

Una vez teniendo nuestra data ordenada y en formato de lectura, haremos los mapas.

4
1. Leyendo shapes files.
La primera forma será generar mapas a traves del uso de shapes. Existen muchas fuentes para bajar este tipo
de archivos las cuales encontraran en las referencias.
En este caso, yo bajé la de las regiones X y XI del sur de Chile, en donde se desarrolla la pesquería de erizo.
Tambien podemos llamar el archivo con otra función llamada readShapePoly. Queda a critero del analista,
mapzona<-readOGR(dsn="C:/Users/mauricio.mardones/Documents/IFOP/Maps_R/Maps_2",
layer="10y11")

## OGR data source with driver: ESRI Shapefile


## Source: "C:\Users\mauricio.mardones\Documents\IFOP\Maps_R\Maps_2", layer: "10y11"
## with 255 features
## It has 39 fields
mapzona2 <- readShapePoly("10y11.shp")

## Warning: readShapePoly is deprecated; use rgdal::readOGR or sf::st_read


Lo siguiente es convertir el archivo a formato para ser leido en ggplot2.
mapzona_df <- fortify(mapzona)

## Regions defined for each Polygons


El mapa se lee con geom_polygon y los datos se leen en la función geom_point
# Breaks para Legenda
mybreaks <- c(1, 15, 50)

Lo primero es ver solo distribución de puntos en el espacio. Aqui filtro un año por que mi base es muy pesada
y se demora en plotear. #Dejo solo el 2019
ggplot() +
geom_polygon(data = mapzona_df, aes(x=long, y = lat, group = group),
fill="grey", alpha=0.8) +
geom_point(data=point %>%
filter(ANO_REG == 2019), aes(x=LONGITUD, y=LATITUD), shape=20, colour= "red") +
annotation_north_arrow(location="tr",
height = unit(1.5, "cm"),
width = unit(1.5, "cm"))+
theme_bw(base_size=15) + coord_map() +
xlab(expression(paste(Longitude^o,~'O'))) +
ylab(expression(paste(Latitude^o,~'S')))+
guides( colour = guide_legend()) +
#ggtitle("Capturas Erizo (t) 2019") +
theme(
legend.position="none"
#text = element_text(color = "#22211d"),
#plot.background = element_rect(fill = "#f5f5f2", color = NA),
#panel.background = element_rect(fill = "#f5f5f2", color = NA),
#legend.background = element_rect(fill = "#f5f5f2", color = NA)
#plot.title = element_text(size= 16, hjust=0.1, color = "#4e4d47",
# margin = margin(b = -0.1, t = 0.4, l = 2, unit = "cm")),
)

5
N
−40.0

−42.5
Latitudeo S

−45.0

−47.5

−75 −74 −73 −72 −71


o
Longitude O

Figure 1: Distribución
6
Luego podemos visualizar magnitudfes de nuestra variable de interes en el espacio, en este caso magintud en
capturas.
Aquí filtro un año por que mi base es muy pesada y se demora en plotear. Dejo solo el 2019.
ggplot() +
geom_polygon(data = mapzona_df, aes(x=long, y = lat, group = group),
fill="grey", alpha=0.8) +
geom_point(data=point %>%
filter(ANO_REG == 2019), aes(x=LONGITUD, y=LATITUD,
size=CAPT, color=CAPT, alpha=CAPT),
shape=20) +
scale_size_continuous(name="Capt (t.)", range=c(1,12), breaks=mybreaks) +
scale_alpha_continuous(name="Capt (t.)", range=c(1, 12), breaks=mybreaks) +
scale_color_viridis(option="inferno", trans="log", breaks=mybreaks, name="Capt (t.)" ) +
annotation_north_arrow(location="tr",
height = unit(1.5, "cm"),
width = unit(1.5, "cm"))+
theme_bw(base_size=15) + coord_map() +
xlab(expression(paste(Longitude^o,~'O'))) +
ylab(expression(paste(Latitude^o,~'S')))+
guides( colour = guide_legend()) +
#ggtitle("Capturas Erizo (t) 2019") +
theme(
legend.position="right"
#text = element_text(color = "#22211d"),
#plot.background = element_rect(fill = "#f5f5f2", color = NA),
#panel.background = element_rect(fill = "#f5f5f2", color = NA),
#legend.background = element_rect(fill = "#f5f5f2", color = NA)
#plot.title = element_text(size= 16, hjust=0.1, color = "#4e4d47",
# margin = margin(b = -0.1, t = 0.4, l = 2, unit = "cm")),
)

7
N
−40.0

−42.5

Capt (t.)
Latitudeo S

1
15

−45.0 50

−47.5

−75 −74 −73 −72 −71


o
Longitude O

Figure 2: Mapa de Magnitudes de la variable de interes


8
Otra forma es sacando el fondo, solo por estética, con theme_void
ggplot() +
geom_polygon(data = mapzona_df, aes(x=long, y = lat, group = group),
fill="grey", alpha=0.8) +
geom_point(data=point %>%
filter(ANO_REG == 2019), aes(x=LONGITUD, y=LATITUD,
size=CAPT, color=CAPT, alpha=CAPT),
shape=20) +
scale_size_continuous(name="Capt (t.)", range=c(1,12), breaks=mybreaks) +
scale_alpha_continuous(name="Capt (t.)", range=c(1, 12), breaks=mybreaks) +
scale_color_viridis(option="plasma", trans="log", breaks=mybreaks, name="Capt (t.)" ) +
annotation_north_arrow(location="tr",
height = unit(1.5, "cm"),
width = unit(1.5, "cm"))+
theme_void(base_size=15) + coord_map() +
xlab(expression(paste(Longitude^o,~'O'))) +
ylab(expression(paste(Latitude^o,~'S')))+
guides( colour = guide_legend()) +
#ggtitle("Capturas Erizo (t) 2019") +
theme(
legend.position="right"
#text = element_text(color = "#22211d"),
#plot.background = element_rect(fill = "#f5f5f2", color = NA),
#panel.background = element_rect(fill = "#f5f5f2", color = NA),
#legend.background = element_rect(fill = "#f5f5f2", color = NA)
#plot.title = element_text(size= 16, hjust=0.1, color = "#4e4d47",
# margin = margin(b = -0.1, t = 0.4, l = 2, unit = "cm")),
)

9
N

Capt (t.)
1
15

50

Figure 3: Mapa sin fondo

10
Ahora podemos ver como se distribuyen los datos en el tiempo. En este caso, mi variable temporal será
“MES_REG” y usaré un facet_wrap
ggplot() +
geom_polygon(data = mapzona_df, aes(x=long, y = lat, group = group),
fill="grey", alpha=0.8) +
geom_point(data=point %>%
filter(ANO_REG == 2019), aes(x=LONGITUD, y=LATITUD,
size=CAPT, color=CAPT, alpha=CAPT),
shape=20) +
scale_size_continuous(name="Capt (t.)", range=c(1,12), breaks=mybreaks) +
scale_alpha_continuous(name="Capt (t.)", range=c(1, 12), breaks=mybreaks) +
scale_color_viridis(option="cividis", trans="log", breaks=mybreaks, name="Capt (t.)" ) +
annotation_north_arrow(location='tr',
height = unit(0.7, "cm"),
width = unit(0.7, "cm"))+
theme_void(base_size=15) + coord_map() +
xlab(expression(paste(Longitude^o,~'O'))) +
ylab(expression(paste(Latitude^o,~'S')))+
guides( colour = guide_legend()) +
facet_wrap(~MES_ARR, ncol = 5)+
#ggtitle("Capturas Erizo (t) 2019") +
theme(
legend.position="right"
#text = element_text(color = "#22211d"),
#plot.background = element_rect(fill = "#f5f5f2", color = NA),
#panel.background = element_rect(fill = "#f5f5f2", color = NA),
#legend.background = element_rect(fill = "#f5f5f2", color = NA)
#plot.title = element_text(size= 16, hjust=0.1, color = "#4e4d47",
# margin = margin(b = -0.1, t = 0.4, l = 2, unit = "cm")),
)

11
1 2 3 4 5

N N N N N

Capt (t.)
1
6 7 8 9 10 15

N N N N N 50

12
2. Usando marmap library.
Esta libreria permite extraer lineas de costa y batimetrias con sus funciones. Cada cual define sus limites
expresados en coordenadas.
Esta librería es útil si uno no tiene shapes de su área da estudio, sin embargo, no tienen muy buena resolución
Obtenemos los limites de la zona de estudio. En este caso las regiones X y XI.
bathy <- getNOAA.bathy(-75,-72,-46,-41, resolution=1, keep=TRUE)

## File already exists ; loading 'marmap_coord_-75;-46;-72;-41_res_1.csv'


Creo paleta de colores por que tiene por default unas muy báicas
blues <- c("lightsteelblue4", "lightsteelblue3",
"lightsteelblue2", "lightsteelblue1")
greys <- c(grey(0.6), grey(0.93), grey(0.99))

Ahora ploteo los datos de capturas de erizo del año 2019


autoplot(bathy, geom=c("r", "b"), coast=TRUE, show.legend=FALSE) +
scale_fill_gradient2(low = blues, high = greys)+
#scale_fill_gradient2(low="aliceblue", mid="white", high="white")+
#scale_fill_etopo() + labs(x = "Longitude", y = "Latitude")+
geom_point(data=point %>%
filter(ANO_REG == 2019), aes(x=LONGITUD, y=LATITUD,
size=CAPT, colour=CAPT, alpha=CAPT), shape=20)+
scale_size_continuous(name="Capt (t.)", range=c(1,12), breaks=mybreaks) +
#scale_alpha_continuous(name="Capt (t.)", range=c(1, 12), breaks=mybreaks) +
scale_color_viridis(option="inferno", trans="log",
breaks=mybreaks, name="Capt (t.)" ) +
annotation_north_arrow(location='tr',
height = unit(1.5, "cm"),
width = unit(1.5, "cm"))+
guides( colour = guide_legend()) +
scale_alpha(guide = 'none')+
#facet_wrap(~MES_REG ,ncol = 5)+
#annotate("text", x = -74, y = -41.5, label = "PMZC")+
xlab(expression(paste(Longitude^o,~'O'))) +
ylab(expression(paste(Latitude^o,~'S')))+
theme(legend.position = "right")

13
−41

−42

−43

Capt (t.)
Latitudeo S

1
15

50

−44

−45

−46
−75 −74 −73 −72
Longitudeo O

14
Ahora ploteo los datos de capturas de erizo del año 2019 a traves dew la escala temporal de meses.
autoplot(bathy, geom=c("r", "b"), coast=TRUE, show.legend=FALSE) +
scale_fill_gradient2(low = blues, high = greys)+
#scale_fill_gradient2(low="aliceblue", mid="white", high="white")+
#scale_fill_etopo() + labs(x = "Longitude", y = "Latitude")+
geom_point(data=point %>%
filter(ANO_REG == 2019), aes(x=LONGITUD, y=LATITUD,
size=CAPT, colour=CAPT, alpha=CAPT), shape=20)+
scale_size_continuous(name="Capt (t.)", range=c(2,15), breaks=mybreaks) +
#scale_alpha_continuous(name="Capt (t.)", range=c(1, 12), breaks=mybreaks) +
scale_color_viridis(option="inferno", trans="log",
breaks=mybreaks, name="Capt (t.)" ) +
annotation_north_arrow(location='tr',
height = unit(0.7, "cm"),
width = unit(0.7, "cm"))+
guides( colour = guide_legend()) +
scale_alpha(guide = 'none')+
facet_wrap(~MES_REG ,ncol = 5)+
#annotate("text", x = -74, y = -41.5, label = "PMZC")+
xlab(expression(paste(Longitude^o,~'O'))) +
ylab(expression(paste(Latitude^o,~'S')))+
theme(legend.position = "right")

15
1 2 3 4 5
−41

N N N N N
−42

−43

−44

−45
Capt (t.)
1
Latitudeo S

−46
15
6 7 8 9 10
−41
50
N N N N N
−42

−43

−44

−45

−46
−75 −74 −73 −72
−75 −74 −73 −72
−75 −74 −73 −72
−75 −74 −73 −72
−75 −74 −73 −72
Longitudeo O

16
3. Generando mapas con un raster.
En este ultimo ejemplo, generaremos los mapas disponibles en bases globales. Saco datos de un raster
disponible en la web
chile<-getData('GADM',country='CHL',level=1)

Visualizo los nombres y codes de cada region para seleccionar mis objetivos de analisis. Luego extraigo X y
XI regiones.
chile@data$NAME_1

## [1] "Aisén del General Carlos Ibáñez del Campo"


## [2] "Antofagasta"
## [3] "Araucanía"
## [4] "Arica y Parinacota"
## [5] "Atacama"
## [6] "Bío-Bío"
## [7] "Coquimbo"
## [8] "Libertador General Bernardo O'Higgins"
## [9] "Los Lagos"
## [10] "Los Ríos"
## [11] "Magallanes y Antártica Chilena"
## [12] "Maule"
## [13] "Ñuble"
## [14] "Región Metropolitana de Santiago"
## [15] "Tarapacá"
## [16] "Valparaíso"
pm <- subset(chile [c(1,9),])

Ahora genero un plot para chequear mi selección,


plot(pm)

17
Figure 4: Mapa de chequeo de zonas
18
Ahora paso el raster a un formato para ser usado por ggplot usando la función fortify como lo habiamos
realizado anteriormente
pm <- fortify(pm)

## Regions defined for each Polygons


ggplot() +
geom_polygon(data=pm,aes( x= long, y=lat, group= group),
fill="gray", alpha=0.99)+
geom_point(data=point %>%
filter(ANO_REG == 2019), aes(x=LONGITUD, y=LATITUD,
colour=CAPT, size=CAPT, alpha=1/10))+
annotation_north_arrow(location='tr')+
scale_size_continuous(name="Capt (t.)", range=c(1,12), breaks=mybreaks) +
#scale_alpha_continuous(name="Capt (t.)", range=c(1, 12), breaks=mybreaks) +
scale_color_viridis_c(option="magma",trans="log", breaks=mybreaks, name="Capt (t.)")+
theme_bw() + coord_map() +
scale_alpha(guide="none")+
xlab(expression(paste(Longitude^o,~'O'))) +
ylab(expression(paste(Latitude^o,~'S')))+
guides( colour = guide_legend()) +
theme(panel.background = element_rect(fill = 'aliceblue'))+
#panel.grid.major = element_blank(),
#panel.grid.minor = element_blank())+
theme(legend.position = "right")

19
−40.0

−42.5

Capt (t.)
Latitudeo S

1
15
−45.0

50

−47.5

−75 −74 −73 −72 −71


Longitudeo O

Figure 5: Mapa de raster con disttribución y magnitud de la variable

20
Ahora un mapa de las capturas a través de la escala temporal de la variable, en este caso, meses del año 2019.
ggplot() +
geom_polygon(data=pm,aes( x= long, y=lat, group= group),
fill="gray", alpha=0.99)+
geom_point(data=point %>%
filter(ANO_REG == 2019), aes(x=LONGITUD, y=LATITUD,
colour=CAPT, size=CAPT, alpha=1/10))+
facet_wrap(~MES_REG, ncol = 5)+
annotation_north_arrow(location='tr')+
scale_size_continuous(name="Capt (t.)", range=c(1,12), breaks=mybreaks) +
#scale_alpha_continuous(name="Capt (t.)", range=c(1, 12), breaks=mybreaks) +
scale_color_viridis_c(option="magma",trans="log", breaks=mybreaks, name="Capt (t.)")+
theme_bw() + coord_map() +
scale_alpha(guide="none")+
xlab(expression(paste(Longitude^o,~'O'))) +
ylab(expression(paste(Latitude^o,~'S')))+
guides( colour = guide_legend()) +
theme(panel.background = element_rect(fill = 'aliceblue'))+
#panel.grid.major = element_blank(),
#panel.grid.minor = element_blank())+
theme(legend.position = "right")

21
1 2 3 4 5
−40.0

N N N N N
−42.5

−45.0

−47.5

Capt (t.)
Latitudeo S

6 7 8 9 10 15
−40.0
50

N N N N N
−42.5

−45.0

−47.5

−75 −74 −73 −72 −71 −75 −74 −73 −72 −71 −75 −74 −73 −72 −71 −75 −74 −73 −72 −71 −75 −74 −73 −72 −71
Longitudeo O

Figure 6: Mapa de raster con disttribución y magnitud de la variable en el tiempo


22
Consideraciones
1. Este documento es solo un conjuto de formas de visualizar los datos que se encuentran en libros e
internet. Por ende un collage de muchos libros, manuales y rincones en la web, por ende el mérito es de
los creadores que hacen simple lo complejo.
2. Si lo consideran útil, pueden compartirlo.
3. Agradecería el feedback, detección de errores o sugerencias para mejorar el documento o los mismos
mapas. Por ejemplo, me quedó pendiente el hacer un inside map o mapa de referencia que haré
pronto y también plotear 2 shapes en el mismo mapa. Cosas sencillas pero que ameritan tiempo y
retroalimentación (estoy dispuesto).
4. El code estará en GitHub para tratar de forzarnos a aprender a hacer modificaciones en grupo (pull,
merge, commit, push, pong, bang y todo eso!)
https://github.com/MauroMardones/Maps
5. Link útiles;
https://stackoverflow.com/ Siempre!
https://cougrstats.wordpress.com/tag/tidyverse/
https://www.earthdatascience.org/
https://www.r-graph-gallery.com/index.html

23

También podría gustarte