Introduction

afrilearndata package has good data that can be used to learn more about Spatial Analysis in R especially within the African context. Having vector (with attribute data) and raster (with pixel values), the possibilities of analytic approaches are unlimited. Here, I will barely glimpse tip of the iceberg.

You can find the rmd file in my GitHub account and more about the package here.

Simple mapping of the countries

mf_init(africountries, expandBB = rep(0, 4), theme = 'iceberg')
mf_shadow(africountries, col = 'magenta', cex = 2, add = TRUE) # just for aesthetic
mf_layout(title = 'African countries map with shadow',
          credits = paste0('Sources: Andy South, 2021\nAuthor: Wyclife Agumba Oluoch\n',
          'Package: mapsf ',
          packageVersion('mapsf'), '\nPackage: afrilearndata ', 
          packageVersion('afrilearndata')))
mf_map(africountries, add = TRUE)
mf_label(africountries, var = "name", col = "purple", cex = 0.9, font = 250, bg = "white", r = 0.4, overlap = FALSE, lines = TRUE)

Mapping of population field as proprotional circles

mf_init(africountries, expandBB = rep(0, 4), theme = 'dark')
mf_layout(title = 'African countries population estimate',
          credits = paste0('Sources: IGN, 2018\nAuthor: Wyclife Agumba Oluoch\n',
          'Package: mapsf ',
          packageVersion('mapsf'), '\nPackage: afrilearndata ',
          packageVersion('afrilearndata')))
mf_map(africountries, add = TRUE)
mf_map(x = africountries, var = 'pop_est', type = 'prop', inches = 0.25, 
       col = 'purple', leg_pos = 'topright', leg_title = 'Total population estimate'
)

Mapping population in choropleth protocol

mf_init(africountries, expandBB = rep(0, 4), theme = 'dark')
mf_layout(title = 'African countries population estimate choropleth',
          credits = paste0('Sources: Andy South, 2021\nAuthor: Wyclife Agumba Oluoch\n', 'Package: mapsf ',
                           packageVersion('mapsf'), '\nPackage: afrilearndata ',
                           packageVersion('afrilearndata')))
mf_map(x = africountries, var = "gdp_md_est", type = "choro", breaks = "geom", 
       nbreaks = 5, pal = "Purples", border = "white", lwd = 0.5, leg_pos = "left",
       leg_title = "Numeric estimated gdp", add = TRUE)
mf_inset_on(x = 'worldmap', pos = 'topright')
mf_worldmap(africountries, col = "red")
mf_inset_off()

Extracting population raster data for each country

afripop2020_extract <- africountries %>% 
  mutate(pop_2020 = raster::extract(afripop2020, africountries, fun = mean, na.rm = TRUE))

So cool that we can extract mean values and mutate in the countries data as a new column to be used in subsequent mapping.

mf_init(afripop2020_extract, expandBB = rep(0, 4), theme = 'candy')
mf_layout(title = 'African countries population density 2020',
          credits = paste0('Sources: Andy South, 2021\nAuthor: Wyclife Agumba Oluoch\n', 'Package: mapsf ',
                           packageVersion('mapsf'), '\nPackage: afrilearndata ',
                           packageVersion('afrilearndata')))
mf_map(x = afripop2020_extract, var = "pop_2020", type = "choro", breaks = "geom", nbreaks = 5,
  pal = "YlGnBu", border = "green", lwd = 0.5, leg_pos = "left", 
  leg_title = "African Pop. Density\n(people per km2)", add = TRUE)
mf_inset_on(x = 'worldmap', pos = 'topright')
mf_worldmap(afripop2020_extract, col = "red")
mf_inset_off()

Selective mapping

Here I map only countries whose pop_2020 values are above 100.

afri_pop_2020_100 <- afripop2020_extract %>% filter(pop_2020 > 100)
mf_init(afri_pop_2020_100, expandBB = rep(0, 4), theme = 'dark')
mf_layout(title = 'African countries with over 100 people per km2 in 2020',
          credits = paste0('Sources: Andy South, 2021\nAuthor: Wyclife Agumba Oluoch\n', 'Package: mapsf ',
                           packageVersion('mapsf'), '\nPackage: afrilearndata ',
                           packageVersion('afrilearndata')))
mf_map(x = afri_pop_2020_100, var = "pop_2020", type = "choro", breaks = "geom", nbreaks = 5,
  pal = "YlGnBu", border = "green", lwd = 0.5, leg_pos = "left", 
  leg_title = "African Pop. Density\n(people per km2)", add = TRUE)
mf_label(x = afri_pop_2020_100, var = "name", col = "purple", cex = 0.9, font = 250, bg = "white", r = 0.4, overlap = FALSE, lines = FALSE)
mf_inset_on(x = 'worldmap', pos = 'topright')
mf_worldmap(afri_pop_2020_100, col = "red")
mf_inset_off()

Here I map only countries whose population density values by 2020 fall below 20 people per square kilometre.

afri_pop_2020_below_20 <- afripop2020_extract %>% filter(pop_2020 < 20)
mf_init(afri_pop_2020_below_20, expandBB = rep(0, 4), theme = 'dark')
mf_layout(title = 'African countries with below 20 people per km2 in 2020',
          credits = paste0('Sources: Andy South, 2021\nAuthor: Wyclife Agumba Oluoch\n', 'Package: mapsf ',
                           packageVersion('mapsf'), '\nPackage: afrilearndata ',
                           packageVersion('afrilearndata')))
mf_map(x = afri_pop_2020_below_20, var = "pop_2020", type = "choro", breaks = "geom", nbreaks = 5,
  pal = "YlOrRd", border = "green", lwd = 0.5, leg_pos = "left", 
  leg_title = "African Pop. Density\n(people per km2)", add = TRUE)
mf_label(x = afri_pop_2020_below_20, var = "name", col = "purple", cex = 0.9, font = 250, bg = "white", r = 0.4, overlap = FALSE, lines = FALSE)
mf_inset_on(x = 'worldmap', pos = 'topright')
mf_worldmap(afri_pop_2020_below_20, col = "red")
mf_inset_off()

Here is map of the country with maximum population density by 2020

afri_pop_2020_max <- afripop2020_extract %>% filter(pop_2020 == max(pop_2020, na.rm = TRUE))
mf_init(afri_pop_2020_max, expandBB = rep(0, 4), theme = 'dark')
mf_layout(title = 'African country with maximum people per km2 in 2020',
          credits = paste0('Sources: Andy South, 2021\nAuthor: Wyclife Agumba Oluoch\n', 'Package: mapsf ',
                           packageVersion('mapsf'), '\nPackage: afrilearndata ',
                           packageVersion('afrilearndata')))
mf_map(x = afri_pop_2020_max, var = "pop_2020", type = "choro", breaks = "geom", nbreaks = 1,
  pal = "YlGnBu", border = "green", lwd = 0.5, leg_pos = "left", 
  leg_title = "African Pop. Density\n(people per km2)", add = TRUE)
mf_label(x = afri_pop_2020_max, var = "name", col = "white", cex = 2, font = 250, bg = "white", r = 0.4, overlap = FALSE, lines = FALSE)
mf_inset_on(x = 'worldmap', pos = 'topright')
mf_worldmap(afri_pop_2020_max, col = "red")
mf_inset_off()

Here is map of the country with least/minimum population density by 2020

afri_pop_2020_min <- afripop2020_extract %>% filter(pop_2020 == min(pop_2020, na.rm = TRUE))
mf_init(afri_pop_2020_min, expandBB = rep(0, 4), theme = 'dark')
mf_layout(title = 'African countries with minimum people per km2 in 2020',
          credits = paste0('Sources: Andy South, 2021\nAuthor: Wyclife Agumba Oluoch\n', 'Package: mapsf ',
                           packageVersion('mapsf'), '\nPackage: afrilearndata ',
                           packageVersion('afrilearndata')))
mf_map(x = afri_pop_2020_min, var = "pop_2020", type = "choro", breaks = "geom", nbreaks = 1,
  col = "cyan", border = "green", lwd = 0.5, leg_pos = "left", 
  leg_title = "African Pop. Density\n(people per km2)", add = TRUE)
mf_label(x = afri_pop_2020_min, var = "name", col = "white", cex = 2, font = 250, bg = "white", r = 0.4, overlap = FALSE, lines = FALSE)
mf_inset_on(x = 'worldmap', pos = 'topright')
mf_worldmap(afri_pop_2020_min, col = "red")
mf_inset_off()

land_cover <- rast(system.file("extdata","afrilandcover.grd", package="afrilearndata", mustWork=TRUE))
mf_init(land_cover, expandBB = rep(0, 4), theme = 'dark')
mf_raster(land_cover, add = TRUE, bgalpha = 0.1)

The raster for the whole continent can be cropped and masked for a specific country extent. Here I do one for Kenya.

kenya_land_cover <- crop(land_cover, africountries[africountries$name=='Kenya',])
kenya_mask <- raster::mask(kenya_land_cover, vect(africountries[africountries$name == 'Kenya',]))
kenya_sf <- africountries[africountries$name == 'Kenya',]
mf_init(kenya_mask, expandBB = rep(0, 4), theme = 'dark')
mf_raster(kenya_mask, add = TRUE, bgalpha = 0.1)
mf_layout(title = 'Kenyan Land Cover',
          credits = paste0('Sources: Andy South, 2021\nAuthor: Wyclife Agumba Oluoch\n', 'Package: mapsf ',
                           packageVersion('mapsf'), '\nPackage: afrilearndata ',
                           packageVersion('afrilearndata')))
mf_map(x = kenya_sf, add = TRUE, col = 'transparent', lwd = 15, border = 'purple')
mf_label(x = kenya_sf, var = "name", col = "blue", cex = 2, font = 250, bg = "white", r = 0.4, overlap = FALSE, lines = FALSE)
mf_inset_on(x = 'worldmap', pos = 'topright')
mf_worldmap(kenya_sf, col = "red")
mf_inset_off()

As I said earlier, this is a mere glimpse of iceberg tip. The scale bars in the maps could be misleading as they are in degrees and not kms. In other words, I should have projected the data as follows:

kenya_mask_reproj <- terra::project(kenya_mask, "EPSG:21096")
kenya_sf_reproj <- st_transform(kenya_sf, "EPSG:21096")
mf_init(kenya_mask_reproj, expandBB = rep(0, 4), theme = 'dark')
mf_raster(kenya_mask_reproj, add = TRUE, bgalpha = 0.1)
mf_layout(title = 'Kenyan Land Cover',
          credits = paste0('Sources: Andy South, 2021\nAuthor: Wyclife Agumba Oluoch\n', 'Package: mapsf ',
                           packageVersion('mapsf'), '\nPackage: afrilearndata ',
                           packageVersion('afrilearndata')))
mf_map(x = kenya_sf_reproj, add = TRUE, col = 'transparent', lwd = 15, border = 'purple')
mf_label(x = kenya_sf_reproj, var = "name", col = "blue", cex = 2, font = 250, bg = "white", r = 0.4, overlap = FALSE, lines = FALSE)
mf_inset_on(x = 'worldmap', pos = 'topright')
mf_worldmap(kenya_sf_reproj, col = "red")
mf_inset_off()

In this case, the scale of 200km is now correct.

References

Allaire, JJ, Yihui Xie, Jonathan McPherson, Javier Luraschi, Kevin Ushey, Aron Atkins, Hadley Wickham, Joe Cheng, Winston Chang, and Richard Iannone. 2021. Rmarkdown: Dynamic Documents for r. https://CRAN.R-project.org/package=rmarkdown.
Bivand, Roger S., Edzer Pebesma, and Virgilio Gomez-Rubio. 2013. Applied Spatial Data Analysis with R, Second Edition. Springer, NY. https://asdar-book.org/.
Giraud, Timothée. 2021. Mapsf: Thematic Cartography. https://CRAN.R-project.org/package=mapsf.
Henry, Lionel, and Hadley Wickham. 2020. Purrr: Functional Programming Tools. https://CRAN.R-project.org/package=purrr.
Hijmans, Robert J. 2021a. Raster: Geographic Data Analysis and Modeling. https://rspatial.org/raster.
———. 2021b. Terra: Spatial Data Analysis. https://rspatial.org/terra/.
Müller, Kirill, and Hadley Wickham. 2021. Tibble: Simple Data Frames. https://CRAN.R-project.org/package=tibble.
Pebesma, Edzer. 2018. Simple Features for R: Standardized Support for Spatial Vector Data.” The R Journal 10 (1): 439–46. https://doi.org/10.32614/RJ-2018-009.
———. 2021. Sf: Simple Features for r. https://CRAN.R-project.org/package=sf.
Pebesma, Edzer J., and Roger S. Bivand. 2005. “Classes and Methods for Spatial Data in R.” R News 5 (2): 9–13. https://CRAN.R-project.org/doc/Rnews/.
Pebesma, Edzer, and Roger Bivand. 2021. Sp: Classes and Methods for Spatial Data. https://CRAN.R-project.org/package=sp.
R Core Team. 2021. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.
South, Andy. 2021. Afrilearndata: Small Africa Map Datasets for Learning.
Wickham, Hadley. 2016. Ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. https://ggplot2.tidyverse.org.
———. 2019. Stringr: Simple, Consistent Wrappers for Common String Operations. https://CRAN.R-project.org/package=stringr.
———. 2021a. Forcats: Tools for Working with Categorical Variables (Factors). https://CRAN.R-project.org/package=forcats.
———. 2021b. Tidyr: Tidy Messy Data. https://CRAN.R-project.org/package=tidyr.
———. 2021c. Tidyverse: Easily Install and Load the Tidyverse. https://CRAN.R-project.org/package=tidyverse.
Wickham, Hadley, Mara Averick, Jennifer Bryan, Winston Chang, Lucy D’Agostino McGowan, Romain François, Garrett Grolemund, et al. 2019. “Welcome to the tidyverse.” Journal of Open Source Software 4 (43): 1686. https://doi.org/10.21105/joss.01686.
Wickham, Hadley, Winston Chang, Lionel Henry, Thomas Lin Pedersen, Kohske Takahashi, Claus Wilke, Kara Woo, Hiroaki Yutani, and Dewey Dunnington. 2021. Ggplot2: Create Elegant Data Visualisations Using the Grammar of Graphics. https://CRAN.R-project.org/package=ggplot2.
Wickham, Hadley, Romain François, Lionel Henry, and Kirill Müller. 2021. Dplyr: A Grammar of Data Manipulation. https://CRAN.R-project.org/package=dplyr.
Wickham, Hadley, Jim Hester, and Jennifer Bryan. 2021. Readr: Read Rectangular Text Data. https://CRAN.R-project.org/package=readr.
Xie, Yihui. 2014. “Knitr: A Comprehensive Tool for Reproducible Research in R.” In Implementing Reproducible Computational Research, edited by Victoria Stodden, Friedrich Leisch, and Roger D. Peng. Chapman; Hall/CRC. http://www.crcpress.com/product/isbn/9781466561595.
———. 2015. Dynamic Documents with R and Knitr. 2nd ed. Boca Raton, Florida: Chapman; Hall/CRC. https://yihui.org/knitr/.
———. 2021. Knitr: A General-Purpose Package for Dynamic Report Generation in r. https://yihui.org/knitr/.
Xie, Yihui, J. J. Allaire, and Garrett Grolemund. 2018. R Markdown: The Definitive Guide. Boca Raton, Florida: Chapman; Hall/CRC. https://bookdown.org/yihui/rmarkdown.
Xie, Yihui, Christophe Dervieux, and Emily Riederer. 2020. R Markdown Cookbook. Boca Raton, Florida: Chapman; Hall/CRC. https://bookdown.org/yihui/rmarkdown-cookbook.