Data Doodles with Python

Data Doodles with Python

Share this post

Data Doodles with Python
Data Doodles with Python
How to Make a Strava Activity Dashboard with Plotly and Dash - Awesome Strava Charts #6

How to Make a Strava Activity Dashboard with Plotly and Dash - Awesome Strava Charts #6

It's time to connect everything. Learn how to create a Dash app that lets you upload a Strava GPX file to see awesome ride statistics.

Dario Radecic's avatar
Dario Radecic
Oct 25, 2024
∙ Paid

Share this post

Data Doodles with Python
Data Doodles with Python
How to Make a Strava Activity Dashboard with Plotly and Dash - Awesome Strava Charts #6
Share
Article thumbnail (image by author)

This is gonna be a long one.

It’s time to put everything together. It’s time to create a Python app that lets you upload a GPX file and view charts that even Strava’s premium version doesn’t offer. The good part? You already know how to preprocess the data and build the UI components. The bad part? It’s still going to be a painfully involved process.

I’ll guide you through it step by step.

You’ll build the app through 3 checkpoints. In the first one, you’ll make sure the data processing pipeline works and that there’s actually some data to show in the app. In the second, you’ll build every chart as an individual component. And in the third, you’ll connect the dots with Python’s Dash library.

If you want to access all articles with data and code right now, download the eBook and level up your data visualization skills in one afternoon:

https://radecic.gumroad.com/l/yermz

If you’re a paid subscriber, you can download the source code and the data here.

Data Doodles with Python is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.

You’ll need to install the following Python libraries to follow along. Make sure to match the version I’m using:

dash==2.17.1
gpxpy==1.6.2
numpy==2.1.1
pandas==2.2.2
plotly==5.23.0

Let’s start with the first checkpoint - getting the data processing pipeline in order.

Checkpoint #1 - GPX File Processing

You’ll do most of the heavy lifting in this section.

The goal is to create a Python file with functions to load a GPX file, extract chart data, and save it in a JSON file.

Start by organizing your project folder like this (my GPX file is available here):

.
├── data
│   └── src_mtb_ride.gpx
└── utils
    └── gpx_parser.py

All data processing logic happens in utils/gpx_parser.py. Let me walk you through it next.

utils/gpx_parser.py

You’ll need to implement the following functions in the gpx_parser.py file:

  • __load_gpx_file() - Loads a GPX file from a provided parameter.

  • __seconds_to_hhmmss() - Converts an integer representing seconds into HH:MM:SS format. The original route duration is in seconds, so this helper function translates it into a more readable format.

  • __extract_basic_stats() - Returns a dictionary showing a route name, date, duration in HH:MM:SS format, distance in kilometers, total uphill and downhill in meters, and max elevation in meters.

  • __extract_point_data() - Returns a Pandas DataFrame containing individual data points and corresponding values for latitude, longitude, elevation, distance from start, time of day, time and distance from the previous GPS point, speed in meters per second and kilometers per hour, temperature in degrees Celsius, and heart rate.

  • __prep_data_for_charts() - Applies necessary data transformations and resamples it into 1-minute averages. This removes the noise from data and reduces the number of data points.

  • get_map_data() - Gives you a dictionary of all map latitude and longitude pairs, but also a center point for the map.

  • get_common_chart_data() - Returns data for elevation, speed, temperature, and heart rate charts, including X/Y values, title, and axis labels.

  • get_heart_rate_zones_chart_data() - Calculates heart rate zones based on the age provided by the user and returns the values for plotting.

  • get_gradient_charts() - Returns data for two charts: route gradients at a point in time, and gradient ranges as distance traveled in 14 distinct gradient bins.

  • parse_and_save() - Utilizes all of the previous functions to construct a single dictionary with chart data and saves it to disk as a JSON file.

  • load_parsed_data() - Loads the previously saved JSON file and returns it as a Python dictionary.

Yup, it’s a lot.

But you’ve seen all this logic in the previous five articles.

Here’s the code:

Keep reading with a 7-day free trial

Subscribe to Data Doodles with Python to keep reading this post and get 7 days of free access to the full post archives.

Already a paid subscriber? Sign in
© 2025 Dario Radecic
Privacy ∙ Terms ∙ Collection notice
Start writingGet the app
Substack is the home for great culture

Share