7 minute read

Google maps are a great way to share maps that users can interact with and customize for their own purposes. The RgoogleMaps (Loecher and Ropkins 2015) and ggmap (Kahle and Wickham 2013) packages are great tools to download static map queries from Google maps and plot over them. There are some helpful tutorials on using ggmap here and a video here.

This post illustrates how I have implemented the reverse process: creating maps in R and embedding them in Google Maps using the awesome plotKML (Hengl et al. 2015) and rmapshaper (Teucher and Russell 2017) packages. Specifically, I wanted to create a share-able map that overlaid Wisconsin school district boundaries onto the regular Google Maps interface to share with users who are not R users.

Create SpatialPolygonDataFrame in R

Wisconsin’s Department of Public Instruction has published shapefiles for district boundaries and school locations. This post will use the elementary school boundary shapefile. After downloading the file, we need to read the file into R using the rgdal package:1

library(sp)
library(rgdal)
library(tidyverse)

#Download files to temporary directory
fname <- tempfile(fileext = ".zip")
dname <- tempdir()
curl::curl_download("https://dpi.wi.gov/sites/default/files/imce/gis/spatialdata/tl_2013_55_unsd_elsd_harn.zip", 
                    destfile = fname)
unzip(fname, exdir = dname)
#Read data into R
widists <- readOGR(dname, layer="tl_2013_55_unsd_elsd_harn", verbose = FALSE, stringsAsFactors = FALSE) 

plot(widists)

Export to .kml format

This looks about right. The plotKML package writes geographic objects to Keyhole Markup Language the format used by Google Maps, among others. The package comes with a handy vignette that I was able to use to do everything that follows.

library(plotKML)

#Write the district boundaries to a KML file to the working directory
kml_open("mapdata/widists_sm.kml")
kml_layer.SpatialPolygons(widists, 
                          subfolder.name = "Elementary District Boundaries",
                          labels = widists@data$NAME,
                          outline = TRUE,
                          alpha = 0,
                          width = 2,
                          colour = "yellow")

kml_close("mapdata/widists_sm.kml")

Now, this file will open just fine in Google Earth, but unfortunately it is too large for sharing via Google Maps because, at 1.6 MB, it is over the 5 MB limit. Luckily, rmapshaper provides

“a wrapper around the ‘mapshaper’ ‘JavaScript’ library by Matthew Bloch https://github.com/mbloch/mapshaper/ to perform topologically-aware polygon simplification.”

via the ms_simplify() (among other) function.

library(rmapshaper)

widists_sm <- ms_simplify(widists)

#Write the district boundaries to a KML file to the working directory
kml_open("mapdata/widists_sm.kml")
kml_layer.SpatialPolygons(widists_sm, 
                          subfolder.name = "Elementary District Boundaries",
                          labels = widists_sm@data$NAME,
                          outline = TRUE,
                          alpha = 0,
                          width = 3,
                          colour = "yellow")

kml_close("mapdata/widists_sm.kml")

Voila! The new file is only 1.6 MB. Now, all that is left to do is to login to Google Maps, import the widists_sm.kml file and share it. The results are below:

(My) Unresolved issues

Observant readers will notice that I specified many options in the kml_layer.SpatialPolygons() function including alpha, color and (perhaps?) width that do not appear to have translated to the shared Google map above. As far as I can tell, this happens upon importing the file into Google Maps. Opening either file in Google Earth will show yellow lines and transparent polygons.

I am sure there are more, so please reach out in the comments below.

Session Info

devtools::session_info()
##  setting  value                       
##  version  R version 3.3.2 (2016-10-31)
##  system   x86_64, darwin13.4.0        
##  ui       X11                         
##  language (EN)                        
##  collate  en_US.UTF-8                 
##  tz       <NA>                        
##  date     2018-02-09                  
## 
##  package      * version  date       source                           
##  acepack        1.4.1    2016-10-29 CRAN (R 3.3.0)                   
##  aqp            1.15     2017-11-12 CRAN (R 3.3.2)                   
##  assertthat     0.2.0    2017-04-11 cran (@0.2.0)                    
##  backports      1.1.2    2017-12-13 cran (@1.1.2)                    
##  base64         2.0      2016-05-10 CRAN (R 3.3.0)                   
##  bindr          0.1      2016-11-13 cran (@0.1)                      
##  bindrcpp       0.2      2017-06-17 cran (@0.2)                      
##  blogdown       0.5      2018-01-28 Github (rstudio/blogdown@aa98b32)
##  bookdown       0.5      2017-08-20 cran (@0.5)                      
##  broom          0.4.2    2017-02-13 cran (@0.4.2)                    
##  cellranger     1.1.0    2016-07-27 CRAN (R 3.3.0)                   
##  class          7.3-14   2015-08-30 CRAN (R 3.3.2)                   
##  classInt       0.1-24   2017-04-16 CRAN (R 3.3.2)                   
##  cli            1.0.0    2017-11-05 CRAN (R 3.3.2)                   
##  cluster        2.0.5    2016-10-08 CRAN (R 3.3.2)                   
##  codetools      0.2-15   2016-10-05 CRAN (R 3.3.2)                   
##  colorRamps     2.3      2012-10-29 CRAN (R 3.3.0)                   
##  colorspace     1.3-2    2016-12-14 CRAN (R 3.3.2)                   
##  crayon         1.3.4    2017-09-16 CRAN (R 3.3.2)                   
##  curl           3.1      2018-01-30 local                            
##  data.table     1.10.0   2016-12-03 CRAN (R 3.3.2)                   
##  devtools       1.12.0   2016-06-24 CRAN (R 3.3.0)                   
##  digest         0.6.12   2017-01-27 cran (@0.6.12)                   
##  dismo          1.1-4    2017-01-09 CRAN (R 3.3.2)                   
##  dplyr        * 0.7.4    2017-09-28 cran (@0.7.4)                    
##  e1071          1.6-7    2015-08-05 CRAN (R 3.3.0)                   
##  evaluate       0.10.1   2017-06-24 cran (@0.10.1)                   
##  FNN            1.1      2013-07-31 CRAN (R 3.3.0)                   
##  forcats      * 0.2.0    2017-01-23 CRAN (R 3.3.2)                   
##  foreign        0.8-67   2016-09-13 CRAN (R 3.3.2)                   
##  Formula        1.2-1    2015-04-07 CRAN (R 3.3.0)                   
##  geojson        0.2.0    2017-11-08 CRAN (R 3.3.2)                   
##  geojsonio      0.5.0    2017-11-10 CRAN (R 3.3.2)                   
##  geojsonlint    0.2.0    2016-11-03 CRAN (R 3.3.0)                   
##  ggplot2      * 2.2.1    2016-12-30 cran (@2.2.1)                    
##  glue           1.2.0    2017-10-29 CRAN (R 3.3.2)                   
##  gridExtra      2.3      2017-09-09 cran (@2.3)                      
##  gstat          1.1-5    2017-03-12 CRAN (R 3.3.2)                   
##  gtable         0.2.0    2016-02-26 CRAN (R 3.3.0)                   
##  haven          1.1.0    2017-07-09 CRAN (R 3.3.2)                   
##  Hmisc          4.0-1    2016-12-08 CRAN (R 3.3.2)                   
##  hms            0.3      2016-11-22 CRAN (R 3.3.2)                   
##  htmlTable      1.7      2016-10-19 CRAN (R 3.3.0)                   
##  htmltools      0.3.6    2017-04-28 cran (@0.3.6)                    
##  httr           1.3.1    2017-08-20 CRAN (R 3.3.2)                   
##  intervals      0.15.1   2015-08-27 CRAN (R 3.3.0)                   
##  jqr            1.0.0    2017-09-28 CRAN (R 3.3.2)                   
##  jsonlite       1.5      2017-06-01 cran (@1.5)                      
##  jsonvalidate   1.0.0    2016-06-13 CRAN (R 3.3.0)                   
##  knitr          1.18.10  2018-01-28 Github (yihui/knitr@1bdaf39)     
##  lattice        0.20-34  2016-09-06 CRAN (R 3.3.2)                   
##  latticeExtra   0.6-28   2016-02-09 CRAN (R 3.3.0)                   
##  lazyeval       0.2.0    2016-06-12 CRAN (R 3.3.0)                   
##  lubridate      1.7.1    2017-11-03 CRAN (R 3.3.2)                   
##  magrittr       1.5      2014-11-22 CRAN (R 3.3.0)                   
##  maptools       0.8-40   2016-11-15 CRAN (R 3.3.2)                   
##  MASS           7.3-45   2016-04-21 CRAN (R 3.3.2)                   
##  Matrix         1.2-7.1  2016-09-01 CRAN (R 3.3.2)                   
##  memoise        1.0.0    2016-01-29 CRAN (R 3.3.0)                   
##  mnormt         1.5-5    2016-10-15 CRAN (R 3.3.0)                   
##  modelr         0.1.1    2017-07-24 CRAN (R 3.3.2)                   
##  munsell        0.4.3    2016-02-13 CRAN (R 3.3.0)                   
##  nlme           3.1-128  2016-05-10 CRAN (R 3.3.2)                   
##  nnet           7.3-12   2016-02-02 CRAN (R 3.3.2)                   
##  openssl        0.9.5    2016-10-28 CRAN (R 3.3.0)                   
##  pillar         1.1.0    2018-01-14 CRAN (R 3.3.2)                   
##  pixmap         0.4-11   2011-07-19 CRAN (R 3.3.0)                   
##  pkgconfig      2.0.1    2017-03-21 cran (@2.0.1)                    
##  plotKML      * 0.5-8    2017-05-14 CRAN (R 3.3.2)                   
##  plotrix        3.7      2017-12-07 CRAN (R 3.3.2)                   
##  plyr           1.8.4    2016-06-08 CRAN (R 3.3.0)                   
##  psych          1.7.3.21 2017-03-22 cran (@1.7.3.2)                  
##  purrr        * 0.2.4    2017-10-18 CRAN (R 3.3.2)                   
##  R6             2.2.2    2017-06-17 cran (@2.2.2)                    
##  raster         2.5-8    2016-06-02 CRAN (R 3.3.0)                   
##  RColorBrewer   1.1-2    2014-12-07 CRAN (R 3.3.0)                   
##  Rcpp           0.12.13  2017-09-28 cran (@0.12.13)                  
##  readr        * 1.1.1    2017-05-16 CRAN (R 3.3.2)                   
##  readxl         1.0.0    2017-04-18 CRAN (R 3.3.2)                   
##  reshape        0.8.6    2016-10-21 CRAN (R 3.3.0)                   
##  reshape2       1.4.2    2016-10-22 CRAN (R 3.3.0)                   
##  rgdal        * 1.2-5    2016-12-15 CRAN (R 3.3.2)                   
##  rgeos          0.3-21   2016-10-20 CRAN (R 3.3.0)                   
##  rlang          0.1.6    2017-12-21 CRAN (R 3.3.2)                   
##  rmapshaper   * 0.3.0    2017-08-16 CRAN (R 3.3.2)                   
##  rmarkdown      1.8      2017-11-17 cran (@1.8)                      
##  rpart          4.1-10   2015-06-29 CRAN (R 3.3.2)                   
##  rprojroot      1.3-2    2018-01-03 cran (@1.3-2)                    
##  RSAGA          0.94-5   2016-01-05 CRAN (R 3.3.0)                   
##  rstudioapi     0.7      2017-09-07 CRAN (R 3.3.2)                   
##  rvest          0.3.2    2016-06-17 CRAN (R 3.3.0)                   
##  scales         0.5.0    2017-08-24 cran (@0.5.0)                    
##  shapefiles     0.7      2013-01-26 CRAN (R 3.3.0)                   
##  sp           * 1.2-4    2016-12-22 CRAN (R 3.3.2)                   
##  spacetime      1.2-1    2017-09-24 CRAN (R 3.3.2)                   
##  stringi        1.1.5    2017-04-07 cran (@1.1.5)                    
##  stringr      * 1.2.0    2017-02-18 cran (@1.2.0)                    
##  survival       2.40-1   2016-10-30 CRAN (R 3.3.0)                   
##  tibble       * 1.4.1    2017-12-25 CRAN (R 3.3.2)                   
##  tidyr        * 0.7.2    2017-10-16 CRAN (R 3.3.2)                   
##  tidyverse    * 1.2.1    2017-11-14 CRAN (R 3.3.2)                   
##  V8             1.5      2017-04-25 CRAN (R 3.3.2)                   
##  withr          1.0.2    2016-06-20 CRAN (R 3.3.0)                   
##  xfun           0.1      2018-01-22 CRAN (R 3.3.2)                   
##  XML            3.98-1.5 2016-11-10 CRAN (R 3.3.2)                   
##  xml2           1.1.1    2017-01-24 CRAN (R 3.3.2)                   
##  xts            0.9-7    2014-01-02 CRAN (R 3.3.0)                   
##  yaml           2.1.16   2017-12-12 cran (@2.1.16)                   
##  zoo            1.7-14   2016-12-16 CRAN (R 3.3.2)

References

Hengl, Tomislav, Pierre Roudier, Dylan Beaudette, and Edzer Pebesma. 2015. “plotKML: Scientific Visualization of Spatio-Temporal Data.” Journal of Statistical Software 63 (5): 1–25. http://www.jstatsoft.org/v63/i05/.

Kahle, David, and Hadley Wickham. 2013. “ggmap: Spatial Visualization with ggplot2.” The R Journal 5 (1): 144–61. http://journal.r-project.org/archive/2013-1/kahle-wickham.pdf.

Loecher, Markus, and Karl Ropkins. 2015. “RgoogleMaps and loa: Unleashing R Graphics Power on Map Tiles.” Journal of Statistical Software 63 (4): 1–18. http://www.jstatsoft.org/v63/i04/.

Teucher, Andy, and Kenton Russell. 2017. rmapshaper: Client for ’mapshaper’ for ’Geospatial’ Operations. https://CRAN.R-project.org/package=rmapshaper.


  1. I choose to use rgdal instead of the sf (simple features) package because plotKML plays better with sp-class objects.

Say something

Comments

Justin@RProgramming.net

#Nice first post!
I like that you documented all the packages that you were using. I hate it when I try to implement some solution from the web and it used to work but doesn’t anymore.