This current state of the project is early beta, which means that features can be added, removed or changed in backwards incompatible ways.

We published this minor release with one more social tracking app reading data support: Nike Run Club. In this release of RunPandas 0.5.1, we include:

  • Reader module support to Nike Run Club app runpandas.read_nikerun. Reading and handling the JSON tracking file from the Nike Run API into a runpandas.Activity` Reader module support to Nike Run Club app. Reading and handling the JSON tracking file from the Nike Run API into arunpandas.Activity`
  • Read and traverse a directory of Nike Run JSON activities by combining them into a single Activity by the function runpandas.read_dir_nikerun.

What is Runpandas?

Runpandas is a python package based on pandas data analysis library, that makes it easier to perform data analysis from your running sessions stored at tracking files from cellphones and GPS smartwatches or social sports applications such as Strava, MapMyRUn, NikeRunClub, etc. It is designed to enable reading, transforming and running metrics analytics from several tracking files and apps.

What is Nike Run App?

Nike Run Club is one of the most popular free fitness apps that tracks users' runs, capturing time, distance, pace, heart rate (with a fitness tracker), and route with an impressively precise GPS. It is available on Android and IOS platforms.

Main Features

Nike Run Club doesn't offer a official method to export your historical fitness data, unfortunately. However there are several third-party tools available to overcome this issue. One of them is use the open-source tool NRC-Exporter, written in Python, that makes possible by commandline to export all your runs which have associated GPS data and converts them into the GPX format.

Screenshot from the NRC-Exporter Official Repository Website

The NRC exporter makes available the activity JSON files, which after are converted to GPX format. You can work with both of these formats: GPX or JSON. In this post we will show how to load the JSON files. After running the extractor you will have a directory of all JSON files. It should look something like this:

$ tree activities
activities
├── 0019f189-d32f-437f-a4d4-ef4f15304324.json
├── 0069911c-2cc8-489b-8335-8e613a81124s.json
├── 01a09869-0a95-49f2-bd84-75065b701c33.json
└── 07e1fa42-a9a9-4626-bbef-60269dc4a111.json

Now you can load these JSON files into our runpandas reading package.

Reading a single workout

Let's load an exported run from Nike Run using the method runpandas.read_nikerun. This method was specially built for loading the exported JSON Nike Run activities, with all the handling data included.

#Disable Warnings for a better visualization
import warnings
warnings.filterwarnings('ignore')
#!pip install runpandas
import runpandas as rpd
activity = rpd.read_nikerun('./data/nikerun-sample.json')
activity
calories nikefuel steps alt hr lon lat
time
00:00:00 NaN NaN NaN 9.340020 NaN -34.894413 -8.046077
00:00:02.900000 NaN NaN NaN 9.315611 NaN -34.894470 -8.046149
00:00:05.748000 0.447 NaN 7.0 9.323614 NaN -34.894564 -8.046194
00:00:10.586000 0.729 4.327005 14.0 9.260836 138.0 -34.894624 -8.046292
00:00:15.585000 0.728 NaN 14.0 9.334247 139.0 -34.894678 -8.046401
... ... ... ... ... ... ... ...
00:52:39.582000 0.826 7.061214 13.0 9.331132 189.0 -34.894534 -8.046602
00:52:43.582000 0.411 NaN 8.0 9.316407 NaN -34.894465 -8.046533
00:52:44.582000 NaN NaN 7.0 9.512563 NaN -34.894443 -8.046515
00:52:45.582000 NaN NaN NaN 9.324933 NaN -34.894429 -8.046494
00:52:49.582000 NaN 7.064754 7.0 NaN 190.0 -34.894395 -8.046398

727 rows × 7 columns

As shown above, the activity now after loaded can be analysed as any other activity in runpandas!

#compute the common metrics for the running activity such as distance per position, speed, pace, etc.
activity['distpos']  = activity.compute.distance()
activity['speed']  = activity.compute.speed(from_distances=True)
activity_only_moving = activity.only_moving()
activity_only_moving.summary()
Session                           Running: 04-07-2021 11:23:19
Total distance (meters)                                8248.08
Total ellapsed time                     0 days 00:52:49.582000
Total moving time                       0 days 00:47:47.583000
Average speed (km/h)                                   9.36815
Average moving speed (km/h)                            10.2845
Average pace (per 1 km)                        0 days 00:06:24
Average pace moving (per 1 km)                 0 days 00:05:50
Average cadence                                            NaN
Average moving cadence                                     NaN
Average heart rate                                     177.822
Average moving heart rate                              177.957
Average temperature                                        NaN
dtype: object

Reading multiple workouts

We also provides the method runpandas.read_dir_nikerun, which allows the user to read all the tracking files in JSON format in a directory and combined them into a runpandas.Actvity split by sessions based on the timestamp of each activity. Does it sound familiar to you? Exactly, it works as same as the runpandas.read_directory_aggregate, but it is specific for the Nike Run JSON output files.

To illustrate this in action, let's load a session of 6 activities of a single runner exported from he Nike Run account:

#!pip install runpandas
import runpandas as rpd
session = rpd.read_dir_nikerun('./data/nikerun_session')
session
calories nikefuel steps alt hr lon lat
start time
2021-01-31 09:18:46.676000+00:00 00:00:00 NaN NaN NaN 7.308532 NaN -34.891723 -8.046471
00:00:03 0.873 NaN 7.0 7.328482 NaN -34.891698 -8.046576
00:00:06 0.862 NaN 8.0 7.314730 NaN -34.891674 -8.046687
00:00:08.999000 0.150 2.056452 7.0 7.311658 NaN -34.891632 -8.046807
00:00:12.999000 0.509 NaN 14.0 7.334774 NaN -34.891624 -8.046902
... ... ... ... ... ... ... ... ...
2020-09-18 09:23:20.620000+00:00 00:25:38.379000 0.737 NaN 12.0 1.117384 176.0 -34.897463 -8.126419
00:25:42.379000 0.362 5.205709 7.0 0.950017 176.0 -34.897494 -8.126517
00:25:46.378000 0.725 NaN 14.0 0.950000 NaN -34.897489 -8.126607
00:25:52.378000 NaN 5.242402 11.0 0.950000 175.0 -34.897485 -8.126700
00:25:56.378000 NaN NaN NaN NaN NaN -34.897540 -8.126788

3742 rows × 7 columns

print('There are ',  session.session.count(), 'activities')
There are  6 activities
#In this example we compute the distance and the distance per position across all workouts
session = session.session.distance()
#comput the speed for each activity
session = session.session.speed(from_distances=True)
#compute the pace for each activity
session = session.session.pace()
#compute the inactivity periods for each activity
session = session.session.only_moving()
summary = session.session.summarize()
summary
moving_time mean_speed max_speed mean_pace max_pace mean_moving_speed mean_moving_pace mean_cadence max_cadence mean_moving_cadence mean_heart_rate max_heart_rate mean_moving_heart_rate mean_temperature min_temperature max_temperature total_distance ellapsed_time
start
2020-08-16 10:06:00.150000+00:00 00:17:51.850000 2.190390 15.123177 00:07:36 00:01:06 2.237329 00:07:26 NaN NaN NaN 160.772152 179.0 160.788462 NaN NaN NaN 2420.052106 00:18:24.850000
2020-09-18 09:23:20.620000+00:00 00:25:49.378000 2.697902 13.684714 00:06:10 00:01:13 2.707618 00:06:09 NaN NaN NaN 171.626415 183.0 171.623574 NaN NaN NaN 4198.955573 00:25:56.378000
2021-01-31 09:18:46.676000+00:00 00:53:54.324000 2.452860 13.833715 00:06:47 00:01:12 2.615802 00:06:22 NaN NaN NaN 168.152542 186.0 168.320683 NaN NaN NaN 8502.408803 00:57:46.325000
2021-04-02 09:39:34+00:00 00:30:31 2.779288 10.529306 00:05:59 00:01:34 2.800375 00:05:57 NaN NaN NaN 178.212625 189.0 178.203333 NaN NaN NaN 5138.905933 00:30:49.001000
2021-06-11 09:30:44+00:00 00:25:50 2.630604 6.038798 00:06:20 00:02:45 2.693010 00:06:11 NaN NaN NaN 167.064516 180.0 167.285714 NaN NaN NaN 4206.337676 00:26:39.001000
2021-07-04 11:23:19.418000+00:00 00:47:47.583000 2.602263 4.212320 00:06:24 00:03:57 2.856801 00:05:50 NaN NaN NaN 177.821862 192.0 177.956967 NaN NaN NaN 8248.084577 00:52:49.582000
print('Session Interval:', (summary.index.to_series().max() - summary.index.to_series().min()).days, 'days')
print('Total Workouts:', len(summary), 'runnings')
print('Tota KM Distance:', summary['total_distance'].sum() / 1000)
print('Average Pace (all runs):', summary.mean_pace.mean())
print('Average Moving Pace (all runs):', summary.mean_moving_pace.mean())
print('Average KM Distance (all runs):', round(summary.total_distance.mean()/ 1000,2))
Session Interval: 322 days
Total Workouts: 6 runnings
Tota KM Distance: 32.714744667475955
Average Pace (all runs): 0 days 00:06:32.666666
Average Moving Pace (all runs): 0 days 00:06:19.166666
Average KM Distance (all runs): 5.45

As we illustrated above, we can extract several statistics from the session workouts using the same methods and acessors available from runpandas.

What is coming next ?

The next releases will focus on supporting marathon results. It will be awesome, keep tunned!

Thanks

We are constantly developing Runpandas improving its existing features and adding new ones. We will be glad to hear from you about what you like or don’t like, what features you may wish to see in upcoming releases. Please feel free to contact us.