Reviewing my marathon training using MapMyFitness and Pandas
Some fun with data
I’m training for a marathon and I use MapMyFitness (MMF) on my iPhone to track my mileage and pace for each workout. MMF has a public API and Jason Sanford has written a Python front end for it. Which means that I can easily get hold of all my data in Python and explore it with Pandas! To run this notebook, you’ll need:
A scientific Python stack (I recommend Anaconda)
A MapMyFitness account and some recorded workout data
A MapMyFitness API key and access token (go to https://www.mapmyapi.com/io- docs)
You should also
pip install mapmyfitness
Here we go…
The next cell logs into MMF, grabs all my workout data, filters for a specified activity type (running, in my case), and extracts the date, distance and pace for each workout. You’ll need to enter your API key and access token to use it.
Be warned that this function takes a while. You can set verbose=1 to have it update you regularly.
Creating a Pandas Dataframe
The basic Pandas object we’ll use is a dataframe. We can create it as follows:
Let’s see what’s in it. Rather than printing the whole (long) table, I’ll use head to print the first few rows.
As you can see, the workouts are sorted chronologically. I started training (and using MapMyFitness) at the beginning of September, about 4 months ago. At the time I could only comfortably run 2-3 miles, and my pace was slower than 9 minutes per mile.
Now we can easily plot workout distance and pace versus date:
Clearly, I’m running farther and faster as my training program progresses! My pace is down to around 8 minutes per mile, and my typical runs are 5 miles or more. Here’s a histogram of the distances for all my workouts since I started:
How far have I run in total? Here’s a cumulative distance plot, showing that I’ve run more than 200 miles.
Stacked histogram separated by dates
Let’s see how my paces in the last two months compare to those in the first two months. I suspect Pandas has a better way to do this than what I’ve implemented below, but this works…
Next we aggregate data for each week and each month:
Now we can plot the average pace for each week:
The total milage per week:
The plot above shows that I have not been terribly consistent, and have missed a number of workouts due to travel or sickness. For instance, the second week of October I was on vacation in Jordan, and the last week of November I was in Mexico on business.
Or the average mileage per run, by month:
Plotting the routes
MapMyFitness records the actual routes, so we can also plot them.
The resulting map was a bit too much for Jekyll to handle, since it gets embedded as a huge amount of text. Go check it out in the actual notebook. The map is zoomable, thanks to mpld3. You can see a lot of the roads at KAUST, as well as the running paths around the Gardens and through Thuwal park on the Island (see the squiggly line on the top left). The path to the beacon is also obvious. The line at the far right goes to the KAUST stadium, with a partial lap around the track. You can even see where the road to the south Beach has moved due to construction.
If you’re not familiar with KAUST, just compare the plot above with a satellite map.
Post-marathon update (May 2015)
Last Sunday I ran my first marathon! After reading the above, you may be wondering how the rest of my training went. Well, the short story is told by this graph:
Just after my original post, I broke my toe (not from running) and had to stop running for 3-4 weeks. In the meantime, I started biking in order to stay in shape. Later I started getting pain in my calf (still not sure why) when running, so I kept replacing some of my run workouts with biking.
In total, I ran about 550 miles and biked about 370 miles. That sounds like a lot, but my total time spent on training workouts was just over 100 hours. It seems pretty amazing to me that you can condition your body to run a marathon with only that much effort.
My goal was to finish in 4 hours and my finish time was 3:56:44. :-).