A Year of Runkeeper: Analysis and Visualization
About a year ago, I decided to record every single move I make using Runkeeper, and now I want to make some visualizations of my activity throughout the whole year. This is a fairly straightforward project where I will download the data from Runkeeper, then use the Wolfram Language to process, analyze, and visualize my activities. I will show how to create animations like this one that superimposes 24 minutes of all my activities recorded in Barcelona:
To export my Runkeeper data, I follow the steps explained on this page. Another way to get my activities is to connect my Runkeeper account to the Wolfram Language with ServiceConnect. But since this last method is limited to 25 activities, I use the manual export this time.
OK, this is giving me a ZIP file with a pair of CSV files and all my GPX files recorded so far. Let me first save this current notebook inside the unzipped file, and then set the current directory in there:
Now let’s take a look at the header line of “cardioActivities.csv”:
Runkeeper is providing several measurements with different physical units. To correctly interpret these quantities, I will use SemanticImport with the following column types:
This gives me a Dataset object that can be analyzed with ease. Here is how to get some insights about my activities:
1. Count the different types of activities:
2. Compute the average distance:
3. Make a histogram of all the distances:
4. Make a DateListStepPlot of the average speeds:
5. Select activities with distances longer than 10 miles:
6. Find out how many times I would have climbed Mount Everest:
7. Group the activities by their notes:
8. Select activities labeled with the note “Boston” and import their GPX files:
9. Map the starting positions of all the activities:
10. And last but not least, make a TimelinePlot of all the activities:
So far, so good. Next step is to pull out data from the GPX files. Import provides a GeoGraphics with the GPS track drawn in a black line:
But what if I want to get the elevation I was at and the speed I was going? Import has the option "Data" that allows one to access the GPX file in a generic Wolfram Language form (list, string, etc.):
This contains a list of the recorded GeoPosition, elevation, and time stamp points. Since I’m only interested in the points, I define a function that takes the positions and creates a TimeSeries of the elevation:
Given GPX data, this returns an association with a pair of keys:
Now it’s easy to take the "Elevation" to make a DateListPlot colored by elevation:
Or take the "Geometry", Rescale the elevation points, and then use that to color the GPS track by elevation:
Another interesting thing to do with this data is to compute the instantaneous speed. Recently a fellow Wolfram Community member, Sander Huisman, showed how to compute instantaneous speed to colorize his GPS track. Here is the function that I defined to compute a time series of the instantaneous speed from the GeoPosition points and the elevation time series:
If I apply this to the previous example, a DateListPlot can immediately tell me if I had a break during that hike:
Short breaks come from my stops to take pictures of the rock formations that inspired the surrealist painter Salvador Dalí. Let’s map those breaks by colorizing the GPS track according to its speed:
Now that I have a systematic way of taking the positions, elevation, and instantaneous speed of a given activity, it’s time to add these into a new dataset:
A year ago, I moved from the countryside to the city of Barcelona:
To select activities within Barcelona, I could use functions like GeoWithinQ or GeoDistance, but since I added specific notes to my Barcelona activities, these functions are not needed this time:
Before mapping these activities in GeoGraphics, I want to make sure that the activities will be highlighted over a black-and-white uniform map with no labels. To do that, I add advanced GeoStyling options for the GeoBackground to make a negative grayscale background. I also add a GeoScaleBar and I constrain the map in a convenient GeoRange:
Looks good to me. Let’s overlay it with all the activities recorded so far:
I’ve almost covered the entire city! If I map only the starting (yellow) and ending (red) positions, it’s quite clear where I live. For most of these activities, it’s me commuting from one place to another using the city’s bicycle-sharing system:
Now let’s compute the shortest tour to revisit all these places:
It would take a quadcopter about 170 km to visit them all:
Not bad if I compare it to my total annual distance:
One thing that I’ve noticed over this year using Runkeeper is that my path to move from point A (home) to point B (capoeira training center) has been evolving a lot. The thing is that I’m not yet sure what’s the best way to get there by bicycle. The new function TravelDirections might have something new to say here:
When one draws the "TravelPath" for the three different travel methods, "Biking" (green), "Walking" (blue), and "Driving" (red), one will notice that there isn’t just a simple way to get from point A to point B:
When one looks at their TravelDistance, "Walking" is clearly the winner:
But since this path goes through Barcelona’s downtown, or Ciutat Vella (Old City), which is a maze of medieval streets restricted to pedestrians, it would take me nearly an hour to get from point A to point B. The TravelTime for "Biking" is way faster:
I must say that over this year I’ve tried a myriad of different ways to get to point B by bicycle. My current favorite is a variation of the "Driving" path in red:
Now let’s plot all 55 trips colored by their travel times:
The blue/green paths in the center are closer to the "Walking" path, and these seem to be the shortest ways to get to point B. My record time is about 13 minutes:
If one looks at the average time, this is quite close to that predicted by the TravelDirectionsData:
This data is really allowing me to time travel over the past year. In the following GeoGraphics, I color the GPS tracks according to speed, and I add the dates for each activity using Tooltip:
It’s time to take each one of these activities as a new frame and animate the whole year. The code to generate the animation below and the animation at the beginning of this post is available at the end of this post as a CDF. I invite you to use my code to analyze your own Runkeeper data. Want more ideas? Have a look at “A Rat Race, or a Great Way to Start the Day.”
Download this post as a Computable Document Format (CDF) file.
This is a very impressive example of “data is beautiful”. Stunning visualisations! Thanks a lot for sharing.
RunKeeper also stores heart rate data and makes it available via API. Is it possible to access that via Mathematica?
Great article! I read it in russian here: https://habrahabr.ru/company/wolfram/blog/302462/
Greetings from Barcelona! Here is nice place to live! =)