|
# edited on 12/31/2014 |
|
|
|
# DanieleCook: Special thanks for insights from flowingdata.com regarding this. |
|
|
|
library(plotKML) |
|
library(plyr) |
|
library(dplyr) |
|
library(fpc) |
|
library(mapproj) |
|
|
|
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. |
|
load("routes.Rdata") |
|
|
|
# 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") %.% |
|
arrange(index) |
|
|
|
|
|
# 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" |
|
} |
|
color |
|
} |
|
|
|
# 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))) { |
|
print(r) |
|
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) |
|
} |
|
dev.off() |
|
} |
When running the script, I got an error. Below is the output: