Pen plotter maps in R

December 18, 2018

(This article was first published on Blog - BS, and kindly contributed to R-bloggers)

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 [email protected] 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 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 on topics such as: Data science, Big Data, R jobs, visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...

If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Comments are closed.

Search R-bloggers


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)