Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Create HeatMap of Runkeeper's data (forked)

Special Thanks to DanieleCook


How to Install

use R shell and install plotKML, plyr, dplyr, fpc, and mapproj

 install.packages("packagename", dependencies=TRUE)

Put the R script in the folder containing Runkeeper's *.gpx & *.csv files.

Edit the script at line 11 change the num_locations variable to your number of locations where you run. Example : if I ran in New York & London, i will put 2


Rscript plot_runkeeper.R

Here we go!

Work in progress

Add elevation parameter.

find . -type f -name '*.gpx' -print | while read filename; do
echo "$filename";
cat "$filename"|grep " <trkpt"|head -n 1;
done > output.txt
# edited on 12/31/2014
# DanieleCook: Special thanks for insights from regarding this.
num_locations <- 5
# Usage: Place this script in the directory containing your runkeeper data. You can run from terminal using 'Rscript map_runkeeper.R', or
# set your working directory to the location and run within RStudio (use setwd("~/location/of/runkeeper/data")).
# See below on how to set the number of clusters.
# GPX files downloaded from Runkeeper
files <- dir(pattern = "\\.gpx")
# Generate vectors for data frame
index <- c()
latitude <- c()
longitude <- c()
file <- c()
c <- 1 # Set up Counter
for (f in 1:length(files)) {
curr_route <- readGPX(files[f])
# Treat interrupted GPS paths as seperate routes (useful if you occasionally stop running..walk for a bit, and start again like I do.)
for (i in curr_route$tracks[[1]]) {
c <- c + 1
location <- i
file <- c(file,rep(files[f], dim(location)[1]))
index <- c(index, rep(c, dim(location)[1]))
latitude <- c(latitude, location$lat)
longitude <- c(longitude, location$lon)
routes <- data.frame(cbind(index, latitude, longitude,file))
# Because the routes dataframe takes a while to generate for some folks - save it!
save(routes, file="routes.Rdata")
# Use to load as needed.
# Fix data types
routes$file <- as.character(routes$file)
routes$latitude <- as.numeric(levels(routes$latitude)[routes$latitude])
routes$longitude <- as.numeric(levels(routes$longitude)[routes$longitude])
routes <- transform(routes, index = as.numeric(index))
# Load Meta Data
meta_data <- read.csv("cardioActivities.csv", stringsAsFactors=FALSE)
colnames(meta_data)[which(names(meta_data) == "GPX.File")] <- "file"
# Bind routes
routes <- left_join(routes, meta_data, by="file") %.%
# Use this function specify activity color if you have multiple activities.
activity_color <- function(activity) {
if (activity=="Cycling") {
color = "#00000060"
} else if (activity=="Hiking") {
color = "#00000060"
} else {
color = "#0080ff60"
# Identify clusters of points, which will correspond to locations you have run. For example,
# I have run in Boston, Iowa City, Chicago, and a few other cities. You will want to set the minimum krange
# to the number of cities you have run in (5 in my case).
clusters <- pamk(routes[,c("latitude", "longitude")], krange=num_locations:20, diss=T, usepam=F)$pamobject$medoids
# Plot Everything
for (r in 1:max(row(clusters))) {
lat_range <- clusters[r,][1] + rnorm(20, sd=0.1)
lon_range <-clusters[r,][2] + rnorm(20, sd=0.1)
setroutes <- filter(routes, (latitude > min(lat_range) & latitude < max(lat_range)),
longitude > min(lon_range) & longitude < max(lon_range))
routeIds <- unique(setroutes$index)
# Albers projection
locProj <- mapproject(setroutes$longitude, setroutes$latitude, "rectangular", par=38)
setroutes$latproj <- locProj$x
setroutes$lonproj <- locProj$y
# Map the projected points
pdf(sprintf("%s-all.pdf", r))
plot(setroutes$latproj, setroutes$lonproj, type="n", asp=1, axes=FALSE, xlab="", ylab="")
for (i in routeIds) {
currRoute <- subset(setroutes, index==i)
lines(currRoute$latproj, currRoute$lonproj, col=activity_color(currRoute$Type), lwd=0.4)

This comment has been minimized.

Copy link

@cwt137 cwt137 commented Nov 27, 2016

When running the script, I got an error. Below is the output:

$ Rscript plot_runkeeper.R
plotKML version 0.5-6 (2016-05-02)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:plyr’:

    arrange, count, desc, failwith, id, mutate, rename, summarise,

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union

Loading required package: maps

Attaching package: ‘maps’

The following object is masked from ‘package:plyr’:


Error: could not find function "%.%"
Execution halted
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment