After completing the mapping of our hole or course, the next step is to export all the hard work into a KML file. To do this, simply click on the three vertical dots on the left side of the screen where your project is located. This project works best with geoJSON data, which can be easily converted from the KML file in the following steps. Now, it’s time to move to R.
To prepare for plotting, we will need the following packages: sf (for working with geospatial data), tidyverse (for data cleaning and plotting), stringr (for string matching), and geojsonsf (for converting from KML to geoJSON). The first step is to read the KML file using the st_read() function from sf.
# load libraries
library(sf)
library(tidyverse)
library(stringr)
library(geojsonsf)
kml_df <- st_read(“/Users/adambeaudet/Downloads/erin_hills.kml”)
Excellent! By now, we should have our golf course KML data in R. The data frame should consist of 2 columns: Name (project name, or course name in this case), and geometry (a list of all individual points forming the polygons we traced). As mentioned earlier, let’s convert our KML data to geoJSON and extract the course name and hole numbers.
# convert from KML to geoJSON
geojson_df <- st_as_sf(kml_df, “POLYGON”)
# extracting course name and hole number from polygon name# assuming “course_hole_element” naming convention is used for polygonsgeojson_df$course_name <- str_match(geojson_df$Name, “^(.+)_hole”)[,2] geojson_df$hole_num <- gsub(“.*_hole_(\\\\d+)_.*”, “\\\\1”, geojson_df$Name)
To ensure our maps point due north, we need to project them in a way that preserves direction. This can be achieved using the st_transform() function.
# define a CRS for so map always points due north
crs <- “+proj=lcc +lat_1=33 +lat_2=45 +lat_0=39 +lon_0=-96 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs”
# transform data to CRSgeojson_df <- st_transform(geojson_df, crs)
We’re almost ready to plot, but first, we need to specify how each polygon should be colored in ggplot2. Below is the color palette used in my project, but feel free to customize it.
Additionally, we can calculate the centroids of our polygons with the st_centroid() function in this step to overlay the hole number on each green.
geojson_df <- geojson_df %>%mutate(color = case_when(grepl(“_tee$”, Name) ~ “#57B740”,grepl(“_bunker$”, Name) ~ “#EDE6D3”,grepl(“_water$”, Name) ~ “#2243b6”,grepl(“_fairway$”, Name) ~ “#57B740”,grepl(“_green$”, Name) ~ “#86D14A”,grepl(“_hazard$”, Name) ~ “#094d1d”)) %>%mutate(centroid = st_centroid(geometry))
We are now ready to plot. We can utilize geom_sf(), geom_text(), and even geom_point() for more advanced plotting options. Typically, I remove gridlines, axis labels, and the legend for a cleaner appearance.
ggplot() +geom_sf(data = geojson_df, aes(fill = color), color = “black”) +geom_text(data = filter(geojson_df, grepl(“_green”, Name)),aes(x = st_coordinates(centroid)[, 1],y = st_coordinates(centroid)[, 2],label = hole_num),size = 3, color = “black”, fontface = “bold”, hjust = 0.5, vjust = 0.5) +scale_fill_identity() +theme_minimal() +theme(axis.title.x = element_blank(),axis.title.y = element_blank(),axis.text.x = element_blank(),axis.text.y = element_blank(),plot.title = element_text(size = 16),panel.grid.major = element_blank(),panel.grid.minor = element_blank()) +theme(legend.position = “none”) +labs(title = ‘Erin Hills | Hartford, WI’)
And there you have it — a golf course plotted in R, what a concept!
To view other courses I have plotted at the time of writing this article, you can visit my Shiny app: https://abodesy14.shinyapps.io/golfMapsR/
If you followed along, had fun, or are intrigued, feel free to try mapping your favorite courses and create a Pull Request for the golfMapsR repository that I maintain: https://github.com/abodesy14/golfMapsR With some combined effort, we can create a nice little database of plottable golf courses around the world!