Analysis and visualization of activities from Garmin Connect

Image for post
Image for post

In this article, I’ll explain how to export all your activities data from Garmin Connect with Python, then analyze them to get an insight into data and visualize geodata with Folium, one of the most versatile python library for geo-visualization.

Intro

Today smartwatches and sport-trackers are becoming very popular among athletes and active people. These devices allow us to record a lot of information about activities: GPS-track, heart rate, calories burned, cadence, etc. Such services as Strava, MapMyRun, Garmin Connect (for Garmin devices), etc. collect, store and analyze recorded activities. All of those services provide a lot of insight into activities, however, they lack customization and produce only some basic metrics. About a week ago I started thinking about collecting all my activities data, analyze it, and do a visualization like a geographic heatmap.

Exporting personal data

There are several ways to export data from Garmin Connect and other services. For example, you can manually download every activity, but it will take much time. Also, you can request all your data from any service which complies with GDPR regulation (most of them do), but it could take up to 30 days. Garmin Connect Export [https://github.com/pe-st/garmin-connect-export/] is a python script that can download activities data and gpx-files from Garmin servers. The script is very user friendly: to download all activities with gpx track just run the following command in command line or bash:

where <YOUR_USERNAME> is your Garmin account username. After that, the script asks for your password, and then starts to download files, which can take some time. It took around 6 minutes to download 340 of all my activities. The script creates ‘YYYY-MM-DD_garmin_connect_export/’ folder, where it places *.gpx, *.json and *.csv files.

Data processing

After exporting activities files from Garmin connect let’s take a closer look at them. I use python 3.7 to analyze and visualize data, write my code in jupyter notebooks. First, let’s load ‘actvitities.csv’ into the pandas data frame:

The file contains summary information about all recorded activities. This information includes unique Activity ID, date and time of activity, activity type, duration, distance, etc. In total it has 50 columns. This file is very useful if we want to get some aggregate information, like total distance, average speed, average heart rate, etc. Let’s find that information for my data. I want to calculate the total steps, calories burned, elevation gain duration, distance, and total heartbeats. The ‘activites.csv’ does not contain information about total heartbeats, but it could be easily calculated by multiplying the average heart rate of activity by activity duration in minutes. First, I create a list of the columns, which sum I want to find and sum over those columns:

As we can see for all my 338 activities I made 2 million steps, burned 180 Mega calories (760 M Joules), climbed 25 kilometers (or 15 miles), spend more than 13 days doing those activities, covered 2.5 thousand kilometers (1500 miles) and my heart made more 2.7 million beats. Interesting fact, according to the research of North Caroline State University, all mammals get about a billion heartbeats per lifetime [http://robdunnlab.com/projects/beats-per-life/].

Next, I want to see how many activities of different types I have. For that, I group activities by type and count number of entities in each group:

Now let’s create a pie chart of activities percentage ratios by count:

As we can see most of my activities are running (both indoor and outdoor) and cycling. Another interesting metric to look into is the average heart rate distribution by activity. To plot histogram :

My most probable average heart rate is around 160 beats per minute.

Importing gps data from gpx-files

In addition to information in ‘activities.csv’ file, every activity has its gpx-file with name ‘activity_###.gpx’, where ### — ID number, same as ‘Activity ID’ in ‘activities.csv’ file. Even if an activity does not record GPS data (indoor swimming, or treadmill running) it still has an empty gpx-file. Gpx-file is an XLM schema, which contains gps coordinates of waypoints (lat,lon), timestamp of each waypoint, elevation, and extension field for additional information. The extension field of Garmin activities contains heart rate at a waypoint, but in general, it can contain any additional information with its own structure. I parsed gps-files with gpxpy [https://pypi.org/project/gpxpy/], but it can be treated as a regular XLM file. If gpxpy is not installed in your environment, it can be installed with pip:

To parse gpx-file first I import gpxpy, and then I load gpx-file and parse it:

The parser returns an object with information from gpx-file. This object contains tracks, segments, and waypoints. Usually, each file has only one track with one segment, and a segment contains waypoints:

Each point has the following attributes:

time — timestamp, where waypoint was recorded

latitude, longitude — geographical coordinates of a waypoint

elevation — waypoint elevation in meters

extension — contains ‘hr’, heart rate at waypoint

Getting heart rate from the extension is a little bit trickier because in general extensions can have their own structure. In case of garmin gpx-tracks I pull out heart rate from extension the following way:

I parsed all my files in for loop and stored all information with Activity ID and Activity Type in df_gps_tracks data frame. Now I want to plot locations of all my activities on map. I’m going to calculate mean coordinates for each activity, and plot them with plotly express:

Heat map

I’m using folium to plot gps tracks on a map and make a heatmap. If folium is not installed in your system it can be installed with pip:

and import it

Before plotting tracks, the folium map should be created and TileLayer added if necessary. First I create a map with coordinates of the center lat_m and log_n, which are average latitude and longitude of all my activities. Also, I add two layers: Stamen Toner — black and white built-in map style, MapBox — map layer from map box (in this example I’m using dark theme). To use MapBox you need to get API key from Mapbox

[https://docs.mapbox.com/api/#access-tokens-and-token-scopes]

To distinguish different activities tracks on the map I created a color dictionary:

Next, I add tracks to the map with PolyLine method folium. PolyLine accepts tuple or list of point coordinates:

And at the last step, I save the map with tracks into HTML file:

Preview: https://andyakrn.github.io/activities_heatmap/

To create Heatmap I use Heatmap plugin for folium:

Heatmap preview: https://andyakrn.github.io/activities_heatmap/Gpx_heatmap.html

As you can see it is not so hard to export all your activities GPS data from Garmin and plot it with folium. Folium provides a lot of flexibility in plotting different geographical data. If you want to experiment with my code you can find full code at GitHub: [https://github.com/andyakrn/activities_heatmap]

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store