This is an R Markdown Notebook which illustrates basic functions provided by the simple features (sf) and the tidyverse libraries. It aims to diffuse R geospatial functionalities for students of Geomatica Basica at Universidad Nacional de Colombia.
The first step is to install the required libraries:
#install.packages(c("tidyverse", "sf"))
Then, we need to load the two libraries:
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.0 ──
## ✓ ggplot2 3.3.0 ✓ purrr 0.3.3
## ✓ tibble 2.1.3 ✓ dplyr 0.8.5
## ✓ tidyr 1.0.2 ✓ stringr 1.4.0
## ✓ readr 1.3.1 ✓ forcats 0.5.0
## ── Conflicts ────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
library(sf)
## Linking to GEOS 3.5.1, GDAL 2.2.2, PROJ 4.9.2
Now, we can read a shapefile representing Colombian departments which has been previously downloaded from DIVA-GIS.
deptos <- read_sf("./colombia/COL_adm1.shp")
We can know what is the contents of the deptos object:
head(deptos)
It’s very useful to review basic functions provided by the sf library. For example, to know what is the coordinate reference system of the vector data stored in the deptos object we can use the st_crs function:
st_crs(deptos)
## Coordinate Reference System:
## EPSG: 4326
## proj4string: "+proj=longlat +datum=WGS84 +no_defs"
A good starting point to understand data is to plot the data. We can use the ggplot functionalities:
ggplot() + geom_sf(data = deptos)
It is possible to use any coordinate reference system to plot the data. However, it is not right to use a coordinate reference system which has been explicitly defined for another country or region. More information on EPSG codes can be found here
# The CRS 3978 is used in Canada
ggplot() + geom_sf(data = deptos) + coord_sf(crs=st_crs(3978))
Look for the properties of the CRS with EPSG code 32618. It corresponds to UTM 18 N. In case we need to use such CRS,it is necessary to convert the spatial object from EPSG4326 into EPSG:32618.
deptos_utm <- st_transform(deptos, crs = st_crs(32618))
deptos_utm
ggplot() + geom_sf(data = deptos_utm)
As we are interested only in one departament, we can filter the data. Review the following chunk of code and change it to match your department:
antioquia <- deptos %>% filter(NAME_1 == "Antioquia")
Let’s plot the new object:
ggplot() + geom_sf(data = antioquia)
We can repeat the previous steps to load the Colombian municipalities and filter the Antioquian ones:
munic <- read_sf("./colombia/COL_adm2.shp")
mun_antioquia <- munic %>% filter(NAME_1 == "Antioquia")
ggplot() + geom_sf(data = mun_antioquia)
mun_antioquia
antioquia_points<- st_centroid(mun_antioquia)
## Warning in st_centroid.sf(mun_antioquia): st_centroid assumes attributes are
## constant over geometries of x
## Warning in st_centroid.sfc(st_geometry(x), of_largest_polygon =
## of_largest_polygon): st_centroid does not give correct centroids for longitude/
## latitude data
antioquia_points <- cbind(mun_antioquia, st_coordinates(st_centroid(mun_antioquia$geometry)))
## Warning in st_centroid.sfc(mun_antioquia$geometry): st_centroid does not give
## correct centroids for longitude/latitude data
A better plot can be produced using the following chunk:
ggplot(antioquia) +
geom_sf() +
geom_sf(data = antioquia_points, fill = "antiquewhite") +
geom_text(data = antioquia_points, aes(x=X, y=Y,label = ID_2), size = 2) +
coord_sf(xlim = c(-78, -73.5), ylim = c(5.3, 9), expand = FALSE)
library(scales)
##
## Attaching package: 'scales'
## The following object is masked from 'package:purrr':
##
## discard
## The following object is masked from 'package:readr':
##
## col_factor
ggplot(antioquia) +
geom_sf(data=antioquia_points, aes(x=X, y=Y, fill =
ID_2), color = "black", size = 0.25) +
geom_text(data = antioquia_points, aes(x=X, y=Y,label = ID_2), size = 2) +
theme(aspect.ratio=1)+
scale_fill_distiller(name="ID_2", palette = "YlGn", breaks = pretty_breaks(n = 5))+
labs(title="Another Map of Antioquia")
## Warning: Ignoring unknown aesthetics: x, y
However, this visualization is not a real map. Anyway, the output can be saved either as a pdf or as a png.
ggsave("antioquia_municipios.pdf")
## Saving 7 x 5 in image
ggsave("map_antioquia.png", width = 6, height = 6, dpi = "screen")
First, let’s install the required library:
#install.packages("leaflet")
Now, load the library:
library(leaflet)
In order to use the library, we need to convert from simple features to spatial points.
ant_points <- as(antioquia_points, 'Spatial')
Uncomment the following command to see what is inside the object:
#head(ant_points)
Get area of municipalities:
install.packages("lwgeom")
## Installing package into '/home/rstudio-user/R/x86_64-pc-linux-gnu-library/3.6'
## (as 'lib' is unspecified)
Load a library:
library(lwgeom)
## Linking to liblwgeom 3.0.0beta1 r16016, GEOS 3.5.1, PROJ 4.9.2
Let’s calculate the area of each municipality (in square meters):
mun_antioquia$area <- st_area(mun_antioquia) #Take care of units
Now, let’s create a new field to store area in square kilometers:
mun_antioquia$km2 <- mun_antioquia$area/(1000000)
Check the output:
mun_antioquia$km2
## Units: [m^2]
## [1] 507.60408 281.74659 131.99541 102.16135 1181.13943 540.10263
## [7] 87.93221 364.57961 1412.77553 222.17398 573.79307 482.78641
## [13] 233.75043 130.72935 221.36748 150.38938 309.02143 225.72397
## [19] 255.26451 409.74933 358.61191 308.97097 2034.38249 465.21183
## [25] 222.97713 152.67026 212.66511 309.89046 78.87443 246.30879
## [31] 170.91354 1320.49864 673.71393 39.00079 262.90943 155.60562
## [37] 201.44867 66.26547 1831.29644 183.02783 220.88909 1927.63127
## [43] 423.67064 64.55167 192.70603 46.77686 225.71517 1315.08305
## [49] 387.27178 101.54419 82.68621 220.66230 82.19749 159.73225
## [55] 81.43762 113.26362 45.62970 23.47969 2129.96167 237.63511
## [61] 177.93366 134.62615 37.04619 200.99640 241.06230 423.52238
## [67] 113.75912 361.37222 80.11718 1574.10821 1200.38203 303.97084
## [73] 491.46259 1160.82451 118.43937 148.43633 392.58891 116.91509
## [79] 1140.18649 543.64472 354.29920 1923.54905 267.50703 215.62236
## [85] 252.58643 21.55404 448.13567 169.30392 764.53825 356.87230
## [91] 151.17818 177.61175 310.80119 443.69131 215.79103 715.29312
## [97] 369.05147 432.29714 204.96476 245.72890 444.90234 871.82295
## [103] 262.35652 1216.27500 1302.79430 188.18380 253.15156 1748.80801
## [109] 139.97416 145.78410 140.09579 3566.77101 242.28989 2642.13520
## [115] 534.07387 121.02665 531.75594 144.63597 1495.85688 487.29555
## [121] 734.33580 896.46719 1825.95416 1021.94188
Again, we need a conversion from simple features to spatial polygons:
ant_mun <- as(mun_antioquia, 'Spatial')
Uncomment the following code to see what is inside the spatial object:
#head(ant_mun)
Now, prepare the plot:
bins <- c(0, 50, 100, 200, 300, 500, 1000, 2000, Inf)
pal <- colorBin("YlOrRd", domain = ant_mun$km2, bins = bins)
labels <- mun_antioquia$NAME_2
labels
## [1] "Abejorral" "Abriaquí"
## [3] "Alejandría" "Amagá"
## [5] "Amalfi" "Andes"
## [7] "Angelópolis" "Angostura"
## [9] "Anorí" "Anzá"
## [11] "Apartadó" "Arboletes"
## [13] "Argelia" "Armenia"
## [15] "Barbosa" "Bello"
## [17] "Belmira" "Betania"
## [19] "Betulia" "Bolívar"
## [21] "Briceño" "Buriticá"
## [23] "Cáceres" "Cañasgordas"
## [25] "Caicedo" "Caldas"
## [27] "Campamento" "Caracolí"
## [29] "Caramanta" "Carepa"
## [31] "Carolina del Principe" "Caucasia"
## [33] "Chigorodó" "Cisneros"
## [35] "Cocorná" "Concepción"
## [37] "Concordia" "Copacabana"
## [39] "Dabeiba" "Don Matías"
## [41] "Ebéjico" "El Bagre"
## [43] "El Carmen de Viboral" "El Santuario"
## [45] "Entrerríos" "Envigado"
## [47] "Fredonia" "Frontino"
## [49] "Gómez Plata" "Giraldo"
## [51] "Girardota" "Granada"
## [53] "Guadalupe" "Guarne"
## [55] "Guatapé" "Heliconia"
## [57] "Hispania" "Itagüí"
## [59] "Ituango" "Jardín"
## [61] "Jericó" "La Ceja"
## [63] "La Estrella" "La Unión de Sucre"
## [65] "Liborina" "Maceo"
## [67] "Marinilla" "Medellín"
## [69] "Montebello" "Murindó"
## [71] "Mutatá" "Nariño"
## [73] "Nechí" "Necoclí"
## [75] "Olaya" "Peñol"
## [77] "Pequé" "Pueblorrico"
## [79] "Puerto Berrío" "Puerto Nare"
## [81] "Puerto Triunfo" "Remedios"
## [83] "Retiro" "Rionegro"
## [85] "Sabanalarga" "Sabaneta"
## [87] "Salgar" "San Andrés de Cuerquia"
## [89] "San Carlos" "San Francisco"
## [91] "San Jerónimo" "San José de la Montaña"
## [93] "San Juan de Urabá" "San Luis"
## [95] "San Pedro de los Milagros" "San Pedro de Urabá"
## [97] "San Rafael" "San Roque"
## [99] "San Vicente" "Santa Bárbara"
## [101] "Santa Fe de Antioquia" "Santa Rosa de Osos"
## [103] "Santo Domingo" "Segovia"
## [105] "Sonsón" "Sopetrán"
## [107] "Támesis" "Tarazá"
## [109] "Tarso" "Titiribí"
## [111] "Toledo" "Turbo"
## [113] "Uramita" "Urrao"
## [115] "Valdivia" "Valparaíso"
## [117] "Vegachí" "Venecia"
## [119] "Vigía del Fuerte" "Yalí"
## [121] "Yarumal" "Yolombó"
## [123] "Yondó" "Zaragoza"
Then, create the plot:
m <- leaflet(ant_mun) %>%
setView(-75.5, 7, 8) %>% addPolygons(
fillColor = ~pal(km2),
weight = 2,
opacity = 1,
color = "white",
dashArray = "3",
fillOpacity = 0.7,
highlight = highlightOptions(
weight = 5,
color = "#666",
dashArray = "",
fillOpacity = 0.7,
bringToFront = TRUE),
label = labels) %>%
addLegend(pal = pal, values = ~km2, opacity = 0.7, title = NULL,
position = "bottomright")
View the plot:
m
Another way of plotting. It may be simpler:
leaflet() %>%
addProviderTiles(providers$Esri.WorldImagery, options= providerTileOptions(opacity = 0.99)) %>%
addPolygons(data = ant_mun, popup= ant_mun$NAME_2,
stroke = TRUE, fillOpacity = 0.25, smoothFactor = 0.25
)
You can try different providers to improve your map. Take advantage of the tab-completion feature to select the preferred base map just scrolling through the list of 110 providers!
Uncomment the following chunk, complete the code and create a beatiful visualization for the capital of your department. In case of any trouble, use the help of R.
#leaflet() %>%
# addProviderTiles(providers$
The following output is just an example:
When your notebook looks fine, publish it on RPubs. Make sure to do it not later than on 25 March.