Pen plotter maps in R

[This article was first published on Blog - BS, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

I made a sweet Christmas present for my friend Clément, who cycles far too much. Last year he got himself a nice custom bicycle made and started documenting his travels.

So I grabbed the lot and started playing, and I pen-plotted his journeys on postcards.

This blog was contributed to R Bloggers

Base map

First order of business is getting and representing borders of the countries travelled. Arcane base R beware.

# Get the world map
worldMap <- rworldmap::getMap(resolution = "high")

# Europe
europe <- c('France', 'United Kingdom')
# Select only the index of states member of the E.U.
country_filtered <- which(worldMap$NAME%in%europe)

# Extract longitude and latitude border's coordinates of countries
# Rebuild a dataframe with just the stuff we want
europeCoords <- lapply(country_filtered, function(i){
  df <- data.frame(worldMap@polygons[[i]]@Polygons[[1]]@coords)
  df$region = as.character(worldMap$NAME[i])
  colnames(df) <- list("long", "lat", "region")

europeCoords <-"rbind", europeCoords)

Parsing GPX files and tracks

Since Clément has done some good work compiling this dataset, we only need to loop over all GPX files we can find in the directories. We've kept data@time to have a look at when the journeys happened.

Oh, and we need to assign a group variable to each unique path in order to be able to separate them when visualising. Otherwise, we'll end up with one single uninterrupted line.

# build riders' paths in df
paths <- data.frame()
for (file in list.files("data/", pattern = "gpx", recursive = TRUE)) {
  track_points <- rgdal::readOGR(paste("data/", file, sep = ""),
                           layer = "track_points")
  track_points@data$time_clean <- ymd_hms(track_points@data$time)

  df1 <- data.frame(track_points@data)
  df2 <- data.frame(track_points@coords)
  df <- bind_cols(df1, df2)

  df.filter <- df %>%
    select(time, coords.x1, coords.x2) %>%
    mutate(group = file)
  colnames(df.filter) <- c('time', 'lon', 'lat', 'group')

  paths <- rbind(paths, df.filter)

> paths %>% head()
                    time       lon      lat                                  group
1 2017/04/08 01:00:45+00 -1.983406 50.71916 17-04-08-hard-boiled-300/gpx/trace.gpx
2 2017/04/08 01:00:57+00 -1.983241 50.71897 17-04-08-hard-boiled-300/gpx/trace.gpx
3 2017/04/08 01:01:03+00 -1.982949 50.71899 17-04-08-hard-boiled-300/gpx/trace.gpx
4 2017/04/08 01:01:15+00 -1.982324 50.71934 17-04-08-hard-boiled-300/gpx/trace.gpx
5 2017/04/08 01:01:27+00 -1.981452 50.71970 17-04-08-hard-boiled-300/gpx/trace.gpx
6 2017/04/08 01:01:32+00 -1.981107 50.71955 17-04-08-hard-boiled-300/gpx/trace.gpx

Visualising and plotting

Easy as pie: our country boundaries are polygons, while the GPS tracks are paths, in ggplot world.

Once happy with a general layout, exporting an SVG is trivial.

ggplot() +
  geom_polygon(data = europeCoords,
    aes(x = long, y = lat, group = region),
      colour = "#DDDDDD",
      fill = "#FFFFFF") +
  geom_path(data = paths,
    aes(lon, lat, group = group),
      alpha = 0.5) +
  theme_opts  + 
  coord_map(projection = "mercator")

Pen plotting

In the output SVG file, the country boundaries and the tracks are in separate <g> groups, and very easy to isolate. This makes plotting the result one group after the other, with two different pens, very easy. There's a video of the plotting below.

To leave a comment for the author, please follow the link and comment on their blog: Blog - BS. offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)