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

It has beeen a while since our last release, this is because we are working hard in new features in our new release of RunPandas 0.4. Let's highlight them:

  • The Activity now provides extra running statistics such as Vertical Altitude Speed (VAM), mean speed, mean pace, gradient, and mean heart rate.
  • Now we provide in our runpandas.MeasureSeries the capability of conversions such as distance conversion (km - miles), latitudes and longitudes (degrees - radians) and pace conversion (min/km and min/mile).
  • There is an auxiliar package for loading activity examples for testing and demo purposes: runpandas.datasets . The goal is to enrich with several real examples in FIT, GPX and TCX format files.
  • Finally, there is a CI workflow for uploading automatically a package to Pypi after release.

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.

Main Features

Support to some new running metrics such as mean pace and mean speed.

First let's explain the differences between mean pace and mean speed. Although both values express similar information, they are the reverse of each other. The Pace is how much time you need to cover a particular distance, while speed is an indicator of the number of meters you are able to cover within one second. These values can be presented different, depending on the measure units used to express these metrics. Pace is given in unit of time per unit of distance, whereas speed is distance over time.

The formulas are:

Speed (m/s) = distance (m) / time (s)

Pace (s/m) = time (sec) / distance (m)

We provide in runpandas new acessors (runpandas.acessors) for computing those metrics:

#Disable Warnings for a better visualization
import warnings
warnings.filterwarnings('ignore')
# !pip install runpandas
import runpandas as rpd
activity = rpd.read_file('./data/sample.tcx')
#compute the distance using haversine formula between two consecutive latitude, longitudes observations.
activity['distpos']  = activity.compute.distance()
#compute the speed normalized per interval.
activity['speed']  = activity.compute.speed(from_distances=True)
activity['speed'].head()
time
00:00:00         NaN
00:00:01    0.333146
00:00:06    0.335758
00:00:12    1.939984
00:00:16    2.295962
Name: speed, dtype: float64
print('Mean speed m/s:', activity.mean_speed())
print('Mean pace s/m:',  activity.mean_pace())
Mean speed m/s: 2.3545989706029533
Mean pace s/m: 0 days 00:00:00.424701

Generally this is shown in different units like speed (km/h) and pace (min/km):

#convert m/s to km/h by multiplying the factor of 3.6
print('Mean speed km/h:', activity.mean_speed() * 3.6)

#We define a auxiliar function to convert the pace from sec/m to min/km:
def convert_pace_secmeters2minkms(seconds):
    from pandas import Timedelta
    pace_min = int((seconds * 1000) / 60)
    pace_sec = int(seconds * 1000 - (pace_min * 60))
    total_seconds = (pace_min * 60) + pace_sec
    return Timedelta(seconds=total_seconds)

pace_min_km = convert_pace_secmeters2minkms(activity.mean_pace().total_seconds())

print('Mean pace min/km:', pace_min_km)
Mean speed km/h: 8.476556294170631
Mean pace min/km: 0 days 00:07:04

Support to gradient and vertical speed.

Gradient is a measure of the route steepness-the magnitude of its incline or slope as compared to the horizontal. Most often presented as a percentage, the gradient of a climb will normally fall somewhere between 3-15 percent. For practical use, it is usually used for estimating the difficulty of the climb during the route.

#Gradient computed through the distance points
activity['grad']  = activity.compute.gradient()
activity['grad']
time
00:00:00         NaN
00:00:01         NaN
00:00:06    0.000000
00:00:12   -0.121218
00:00:16    0.000000
              ...   
00:32:51    0.028739
00:32:56   -0.028715
00:33:02   -0.042557
00:33:07   -0.051672
00:33:11   -0.097842
Name: grad, Length: 383, dtype: float64

VAM (Vertical Altitude Speed) similar to speed except it tracks how fast you go up vertically rather than horizontally between two points. While speed is measured in miles or kilometers per hour, VAM is measured in vertical meters per hour (vmh). It tells you how many meters you would climb if you went up a moderate grade for an hour.

#Vertical Altitude Speed (VAM) in m/s
activity['vam']  = activity.compute.vertical_speed()
activity['vam']
time
00:00:00         NaN
00:00:01    0.000000
00:00:06    0.000000
00:00:12   -0.240336
00:00:16    0.000000
              ...   
00:32:51    0.096118
00:32:56   -0.096118
00:33:02   -0.160217
00:33:07   -0.192285
00:33:11   -0.360504
Name: vam, Length: 383, dtype: float64

Support to other metrics such as mean heart_pace

#Meart heart rate through the activity
'bpm', int(activity.mean_heart_rate())
('bpm', 156)

Some conversion functions available for measure metrics

#convert the speed m/s to km/h
activity['speed'].kph
time
00:00:00          NaN
00:00:01     1.199325
00:00:06     1.208731
00:00:12     6.983941
00:00:16     8.265462
              ...    
00:32:51    11.864734
00:32:56    12.001946
00:33:02    13.600020
00:33:07    13.428554
00:33:11    13.155589
Name: speed, Length: 383, dtype: float64
#gradient converted from degrees to percent
activity['grad'].pct
time
00:00:00          NaN
00:00:01          NaN
00:00:06     0.000000
00:00:12   -12.121772
00:00:16     0.000000
              ...    
00:32:51     2.873890
00:32:56    -2.871543
00:33:02    -4.255745
00:33:07    -5.167165
00:33:11    -9.784157
Name: grad, Length: 383, dtype: float64
#Total Altitude descent and ascent
print('Ascent', sum(activity['alt'].ascent))
print('Descent', sum(activity['alt'].descent))
Ascent 153.80981445000006
Descent -166.30712890300006
#distance from meters to kms
activity['dist'].km
time
00:00:00    0.000000
00:00:01    0.000000
00:00:06    0.001107
00:00:12    0.013003
00:00:16    0.022405
              ...   
00:32:51    4.613642
00:32:56    4.630378
00:33:02    4.652966
00:33:07    4.671573
00:33:11    4.686311
Name: dist, Length: 383, dtype: float64

An example activities package including several real word activities from different formats.

The runpandas package also comes with extra batteries, such as our runpandas.datasets package, which includes a range of example data for testing purposes. There is a dedicated repository with all the data available. An index of the data is kept here.

example_fit = rpd.activity_examples(path='Garmin_Fenix_6S_Pro-Running.fit')
print(example_fit.summary)
print('Included metrics:', example_fit.included_data)
Synced from watch Garmin Fenix 6S

Included metrics: [<MetricsEnum.latitude: 'latitude'>, <MetricsEnum.longitude: 'longitude'>, <MetricsEnum.elevation: 'elevation'>, <MetricsEnum.heartrate: 'heartrate'>, <MetricsEnum.cadence: 'cadence'>, <MetricsEnum.distance: 'distance'>, <MetricsEnum.temperature: 'temperature'>]
rpd.read_file(example_fit.path).head()
enhanced_speed enhanced_altitude unknown_87 fractional_cadence lap session unknown_108 dist cad hr lon lat temp
time
00:00:00 0.000 254.0 0 0.0 0 0 NaN 0.00 0 101 13.843376 51.066280 8
00:00:01 0.000 254.0 0 0.0 0 0 NaN 0.00 0 101 13.843374 51.066274 8
00:00:10 1.698 254.0 0 0.0 0 1 2362.0 0.00 83 97 13.843176 51.066249 8
00:00:12 2.267 254.0 0 0.0 0 1 2362.0 3.95 84 99 13.843118 51.066250 8
00:00:21 2.127 254.6 0 0.5 0 1 2552.0 16.67 87 100 13.842940 51.066231 8

In case of you just only want to see all the activities in a specific file type , you can filter the runpandas.activities_examples, which returns a filter iterable that you can iterate over:

fit_examples = rpd.activity_examples(file_type=rpd.FileTypeEnum.FIT)
for example in fit_examples:
    #Download and play with the filtered examples
    print(example.path)
https://raw.githubusercontent.com/corriporai/runpandas-data/master/activities/Garmin_Fenix_6S_Pro-Running.fit
https://raw.githubusercontent.com/corriporai/runpandas-data/master/activities/Garmin_Fenix2_running_with_hrm.fit
https://raw.githubusercontent.com/corriporai/runpandas-data/master/activities/Garmin_Forerunner_910XT-Running.fit

What is coming next ?

Working hard in advanced running metrics such as power , heart rate zones and the feature of printing the summary of the activity with the main statistics.

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.