3  Draw Political Maps (sf geom_sf)

Author

Chrissy h Roberts

3.1 Background

The sf package provides a seamless integration between R, ggplot, shapefiles, geoJSON and other GIS formats. A bonus here is that sf objects behave like dataframes so you can bind your own data on to an sf object and use your bound data to control things like putting chloropleths on the map.

This shamelessly copies a tutorial found here.

The rnaturalearth project has a great set of shape data for countries of the globe.

3.2 Libraries

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.3     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ ggplot2   3.4.4     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.0
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(sf)
Linking to GEOS 3.11.0, GDAL 3.5.3, PROJ 9.1.0; sf_use_s2() is TRUE
library(knitr)
library(ggspatial)
library("rnaturalearth")
Support for Spatial objects (`sp`) will be deprecated in {rnaturalearth} and will be removed in a future release of the package. Please use `sf` objects with {rnaturalearth}. For example: `ne_download(returnclass = 'sf')`
library("rnaturalearthdata")

Attaching package: 'rnaturalearthdata'

The following object is masked from 'package:rnaturalearth':

    countries110

3.3 Data

#call the polygons
world <- ne_countries(scale = "medium", returnclass = "sf")

3.4 Draw basic polygons

ggplot(data = world) +
    geom_sf()

3.5 Colour the map with continuous variable

ggplot(data = world) +
    geom_sf(aes(fill = pop_est)) +
    scale_fill_viridis_c(option = "plasma", trans = "sqrt")

3.6 Colour the map with factor variable

ggplot(data = world) +
    geom_sf(aes(fill = continent))

3.7 Change the projection with coord_sf

ggplot(data = world) +
    geom_sf(aes(fill = continent))+
    coord_sf(crs = st_crs(3035))

3.8 Focus on a specific region

    ggplot(data = world) +
    geom_sf(aes(fill = continent))+
      coord_sf(xlim = c(-20.15, 34.12), ylim = c(40, 60), expand = FALSE)

3.9 Decorate with scale bar / compass

     ggplot(data = world) +
              geom_sf(aes(fill = continent))+
              coord_sf(xlim = c(-20.15, 34.12), ylim = c(40, 60), expand = FALSE) +
              annotation_scale(location = "br", width_hint = 0.4) +
              annotation_north_arrow(
                    location = "bl", which_north = "true", 
                    pad_x = unit(0.1, "cm"), pad_y = unit(0.3, "cm"),
                    style = north_arrow_fancy_orienteering) 
Scale on map varies by more than 10%, scale bar may be inaccurate

3.10 Identify centroids of each polygon

This will be used to place country name labels

world = st_make_valid(world)
world_points<- st_centroid(world)
Warning: st_centroid assumes attributes are constant over geometries
world_points <- cbind(world, st_coordinates(st_centroid(world$geometry)))

3.11 Add labels

ggplot(data = world) +
              geom_sf(aes(fill = continent))+
              coord_sf(xlim = c(-20.15, 34.12), ylim = c(40, 60), expand = FALSE) +
              annotation_scale(location = "br", width_hint = 0.4) +
              annotation_north_arrow(
                    location = "bl", which_north = "true", 
                    pad_x = unit(0.1, "cm"), pad_y = unit(0.3, "cm"),
                    style = north_arrow_fancy_orienteering) +
              geom_text(data= world_points,aes(x=X, y=Y, label=name),
                              color = "darkblue", 
                              fontface = "bold", 
                              check_overlap = FALSE,
                              size=1.5
                        )
Scale on map varies by more than 10%, scale bar may be inaccurate

3.12 Add other pretty things

ggplot(data = world) +
              geom_sf(aes(fill = continent))+
              coord_sf(xlim = c(-20.15, 34.12), ylim = c(40, 60), expand = FALSE) +
              annotation_scale(location = "br", width_hint = 0.4) +
              annotation_north_arrow(
                    location = "bl", which_north = "true", 
                    pad_x = unit(0.1, "cm"), pad_y = unit(0.3, "cm"),
                    style = north_arrow_fancy_orienteering) +
              geom_text(data= world_points,aes(x=X, y=Y, label=name),
                              color = "darkblue", 
                              fontface = "bold", 
                              check_overlap = FALSE,
                              size=1.5
                        )+
              theme(panel.grid.major = element_line(color = gray(.5), 
                                                    linetype = "dashed", 
                                                    size = 0.5
                                         
                                                    )
                  )
Warning: The `size` argument of `element_line()` is deprecated as of ggplot2 3.4.0.
ℹ Please use the `linewidth` argument instead.
Scale on map varies by more than 10%, scale bar may be inaccurate

3.12.1 Save as PDF

ggsave(filename = "output/political_map.pdf",dpi = 300)
Saving 7 x 5 in image
Scale on map varies by more than 10%, scale bar may be inaccurate

3.13 Test on new data from some shape files

Using shape files can be quite slow, so here we will only use a few polygons

download.file("https://www.abs.gov.au/ausstats/subscriber.nsf/log?openagent&1270055004_sua_2016_aust_shape.zip&1270.0.55.004&Data%20Cubes&1E24D1FB300696D2CA2581B1000E15A5&0&July%202016&09.10.2017&Latest",destfile = "data/SUA_2016_AUST.zip")

unzip(zipfile = "data/SUA_2016_AUST.zip",exdir = "data/")

3.14 Open Data

map = read_sf("data/SUA_2016_AUST.shp") 
map = map [1:20,]

3.15 Plot map

ggplot(data = map) +
              geom_sf()+
              theme(panel.grid.major = element_line(color = gray(.5), 
                                                    linetype = "dashed", 
                                                    size = 0.5
                                                    ),  
                    legend.position="none"

                  )

3.16 Remove data

system("rm data/SUA*")