Maps allow us to easily convey spatial information. Here, we show how to create both static and interactive maps by using several mapping packages including ggplot2, leaflet, mapview, and tmap. We create maps of areal data using several functions and parameters of the mapping packages. We also briefly describe how to plot point and raster data. Then, we show how to create maps of flows among locations with the flowmapblue package.
The areal data we map correspond to sudden infant deaths in in the counties of North Carolina, USA, in 1974 and 1979 which are in the sf package.
The path of the data can be obtained with
system.file() specifying the directory of the data (
"shape/nc.shp") and the package (
Then, the data can be read with the
st_read() function of sf by specifying the path of the data.
We call this data
d, and create variables
vble2 that we wish to map with the values of the sudden infant deaths in years 1974 and 1979, respectively.
library(sf) <- system.file("shape/nc.shp", package = "sf") nameshp <- st_read(nameshp, quiet = TRUE) d $vble <- d$SID74 d$vble2 <- d$SID79 dhead(d)
The ggplot2 package allows us to create graphics based on the grammar of graphics which defines the rules of structuring mathematic and aesthetic elements to build graphs layer-by-layer.
To create a plot with ggplot2, we call
ggplot() specifying arguments
data which is a data frame with the variables to plot, and
mapping = aes() which are aesthetic mappings between variables in the data and visual properties of the objects in the graph such as position and color of points or lines.
Then, we use
+ to add layers of graphical components to the graph. Layers consist of geometries, stats, scales, coordinates, facets and themes. For example, we add objects to the graph with
geom_*() functions (e.g,
geom_point() for points,
geom_line() for lines). We can also add color scales (e.g.,
scale_colour_brewer()), faceting specifications (e.g.,
facet_wrap() splits data into subsets to create multiple plots), and coordinate systems (e.g.,
We can create maps by using the
geom_sf() function and providing a simple feature (
For example, we create a map of sudden infant deaths in North Carolina in 1974 (
vble) with viridis scale as follows.
library(ggplot2) library(viridis) ggplot(d) + geom_sf(aes(fill = vble)) + scale_fill_viridis() + theme_bw()
Plots created with ggplot2 can be saved with the
Alternatively, we can specify a device driver (e.g.,
png("plot.png") ggplot(d) + geom_sf(aes(fill = vble)) + scale_fill_viridis() + theme_bw() dev.off()
Moreover, the plotly package can be used in combination with ggplot2 to create an interactive plot.
Specifically, we can turn a static
ggplot object to an interactive
plotly object by calling the
ggplotly() function of plotly by providing the
library(plotly) <- ggplot(d) + geom_sf(aes(fill = vble)) g ggplotly(g)
The gganimate package can also be used to create animated plots. The syntax of this package is similar to that of ggplot2 and has additional functions to define how data should change along the animation. Information on how to use the gganimate package can be seen at the package’s website.
We can create a leaflet map by calling the
leaflet() function passing the spatial object, and adding layers such as polygons and legends using a number of functions.
sf object that we pass to
leaflet() needs to have a geographic coordinate reference system (CRS) indicating latitude and longitude (EPSG code 4326).
Here, we use the
st_transform() function of sf to transform the data
d which has CRS given by EPSG code 4267 to CRS with EPSG code 4326.
## Coordinate Reference System: ## User input: NAD27 ## wkt: ## GEOGCRS["NAD27", ## DATUM["North American Datum 1927", ## ELLIPSOID["Clarke 1866",6378206.4,294.978698213898, ## LENGTHUNIT["metre",1]]], ## PRIMEM["Greenwich",0, ## ANGLEUNIT["degree",0.0174532925199433]], ## CS[ellipsoidal,2], ## AXIS["latitude",north, ## ORDER, ## ANGLEUNIT["degree",0.0174532925199433]], ## AXIS["longitude",east, ## ORDER, ## ANGLEUNIT["degree",0.0174532925199433]], ## ID["EPSG",4267]]
<- st_transform(d, 4326)d
We create a color palette using the
colorNumeric() function of leaflet specifying the color palette
"YlOrRd" of the RColorBrewer package, and the domain with the possible values that can be mapped (
Then, we create the map using
addTiles() to add a background map to put data into context.
Then, we use
addPolygons() to add the polygons representing counties specifying the color of the border (
color), interior (
fillColor) and opacity (
Finally, we add a legend with
library(leaflet) <- colorNumeric(palette = "YlOrRd", domain = d$vble) pal <- leaflet(d) %>% addTiles() %>% l addPolygons(color = "white", fillColor = ~ pal(vble), fillOpacity = 0.8) %>% addLegend(pal = pal, values = ~vble, opacity = 0.8) l
Note that the default background map added with
addTiles() can be changed by another map with
addProviderTiles() specifying another tile layer.
Examples of tile layers can be seen at the leaflet providers’ website.
We can also use the
addMiniMap() function to add an inset map.
saveWidget() function of htmlwidgets allows us to save the map created to an HTML file.
If we wish to save an image file, we can first save the leaflet map as an HTML file with
saveWidget(), and then capture a static version of the HTML using the
webshot() function of the webshot package.
The use of webshot requires the installation of the external program
PhantomJS which can be installed with
For example, to save the leaflet map
.png we can proceed as follows:
# Saves map.html library(htmlwidgets) saveWidget(widget = l, file = "map.html") # Takes a screenshot of the map.html created and saves it as map.png library(webshot) # webshot::install_phantomjs() webshot(url = "map.html", file = "map.png")
Note we can use
setwd() to get and set, respectively, the current working directory.
This allows us to see where the files were saved.
Moreover, if in
saveWidget() we specify the path where to save
file = "directory/map.html",
the same path needs to be specified in the argument
url = "directory/map.html".
The package webshot2 is meant to be a replacement for webshot.
The webshot2 package uses headless Chrome via the chromote package whereas webshot uses
The mapview package allows us to very quickly create similar interactive maps as leaflet.
Specifically, we just need to use the
mapview() function passing as arguments the spatial object and the variable we want to plot (
The map created is interactive and by clicking each of the areas we can see popups with the data information.
library(mapview) mapview(d, zcol = "vble")
Maps created with
mapview can also be customized to add elements such as legends and background maps.
For example, we can choose another background map by using the argument
map.types, change the color palette with
col.regions, and put a title for the legend with
layer.name as follows:
library(RColorBrewer) <- colorRampPalette(brewer.pal(9, "YlOrRd")) pal mapview(d, zcol = "vble", map.types = "CartoDB.DarkMatter", col.regions = pal, layer.name = "SDI")
An inset map can also be added by using the
addMiniMap() function of leaflet.
<- mapview(d, zcol = "vble") map1 ::addMiniMap(map1@map)leaflet
We can save maps created with mapview by using the
mapshot() function of mapview
HTML file or as a
We can create a side-by-side plot of maps obtained with mapview separated with a slider by using the
| operator. To use the
| operator, we need to install the leaflet.extras2 package. When creating the individual maps with
mapview(), we use a common legend by specifying the same color palette (
col.regions) and breaks (
at) so in both maps colors correspond to the same intervals of values.
# common legend <- colorRampPalette(brewer.pal(9, "YlOrRd")) pal <- seq(min(c(d$vble, d$vble2)), max(c(d$vble, d$vble2)), length.out = 8) at <- mapview(d, zcol = "vble", map.types = "CartoDB.Positron", col.regions = pal, at = at) m1 <- mapview(d, zcol = "vble2", map.types = "CartoDB.Positron", col.regions = pal, at = at) m2 | m2m1