In [49]:
import folium
import pandas as pd
import numpy as np
import os
from geopy.geocoders import Nominatim
import geocoder
import matplotlib.pyplot as plt
import json
from folium import plugins
import branca.colormap as cm
from tqdm import tqdm_notebook
plt.style.use('ggplot')
In [2]:
def get_elevation(lat,lon):
    try:
        return geocoder.google([lat, lon], method='elevation', key=os.environ['GOOGLE_API_KEY']).meters
    except:
        return np.NaN
In [3]:
def read_csv(filename):
    df = pd.read_csv(filename)
    NewLap_idx = df[df.Time == 'New Lap'].index.values
    df['Time'] = pd.to_datetime(df['Time'], errors='coerce')
    df.dropna(how='any',axis=0, subset=['Time'], inplace=True)
    for lab in ['LongitudeDegrees', 'LatitudeDegrees', 'AltitudeMeters', 'heartratebpm/value']:
        df[lab] = df[lab].interpolate()
    df['dist'] = \
        haversine_np(df.LongitudeDegrees.shift(), df.LatitudeDegrees.shift(),
                     df.loc[1:, 'LongitudeDegrees'], df.loc[1:, 'LatitudeDegrees'])
    df['cum_dis'] = df.dist.cumsum()
    df['DeltaTime'] = (df.Time - df.Time.shift()).dt.total_seconds()
    df['Speed'] = df.apply(lambda x: x['dist']/float(x['DeltaTime'])*3600.0 if x['DeltaTime'] > 0.5 else np.NaN, axis=1)
    df['Speed'] = df.apply(lambda x: x['Speed'] if x['Speed'] < 20 else np.NaN, axis=1)
    df['DeltaAltitude'] = df.AltitudeMeters - df.AltitudeMeters.shift()
    df.to_csv('output/csv/' + os.path.basename(filename))
    return df, NewLap_idx
In [4]:
def haversine_np(lon1, lat1, lon2, lat2):
    """
    Calculate the great circle distance between two points
    on the earth (specified in decimal degrees)

    All args must be of equal length.    

    """
    lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, lon2, lat2])

    dlon = lon2 - lon1
    dlat = lat2 - lat1

    a = np.sin(dlat/2.0)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2.0)**2

    c = 2 * np.arcsin(np.sqrt(a))
    km = 6367 * c
    return km
In [4]:
#path = 'data/csv/'
path = 'output/csv'
geolocator = Nominatim()
allFiles = os.listdir(path)
frame = pd.DataFrame(columns=('Date', 'Filename', 'Kilometers', 'Speed', 'Time', 'Climb', 'Lat', 'Long', 'Adress'))
dict_df = dict()
#dict_newlap = dict()
for i, file in tqdm_notebook(enumerate(allFiles)):
    df = pd.read_csv('output/csv/' + file, index_col=0, parse_dates=['Time'])
    #df, newlap = read_csv(path + file)
    dict_df[df['Time'][0].strftime("%Y-%m-%d")] = df
    location = geolocator.reverse(str(df.LatitudeDegrees.mean()) + "," + str(df.LongitudeDegrees.mean()))[0]
    frame.loc[i] = [df['Time'][0], file, df.cum_dis.max(), df.Speed.mean(), df.DeltaTime.sum()/60,
                    df['DeltaAltitude'][df['DeltaAltitude'] > 0].sum(),
                    df.LatitudeDegrees.mean(), df.LongitudeDegrees.mean(), location]

Session manual add

In [5]:
frame.loc[frame[frame['Filename'] == '2017-09-01T05_07_50Z_PT50M7S_Running.csv'].index,'Speed'] = 10.9
frame.loc[frame[frame['Filename'] == '2017-09-01T05_07_50Z_PT50M7S_Running.csv'].index,'Kilometers'] = 8.09
frame.loc[frame[frame['Filename'] == '2017-09-01T05_07_50Z_PT50M7S_Running.csv'].index,'Time'] = 44.5
frame.loc[frame[frame['Filename'] == '2017-09-01T05_07_50Z_PT50M7S_Running.csv'].index,'Climb'] = 130
In [6]:
frame.sort_values('Date', ascending=False)
Out[6]:
Date Filename Kilometers Speed Time Climb Lat Long Adress
31 2017-09-28 17:31:41.836 2017-09-28T17_32_18Z_PT40M33S_Running.csv 7.643801 11.602275 41.166867 742.000 48.822395 2.338011 Le Petit Train, Allée du Bardo, Montsouris, Pa...
1 2017-09-26 17:29:38.784 2017-09-26T17_29_38Z_PT42M55S_Running.csv 8.761183 11.979408 42.932483 890.000 48.822418 2.337851 Le Petit Train, Allée du Bardo, Montsouris, Pa...
53 2017-09-23 09:23:27.402 2017-09-23T09_23_58Z_PT1H59M11S_Running.csv 21.848359 11.175643 119.718800 2166.000 48.780568 2.292178 Avenue Charles Péguy, Sceaux, Antony, Hauts-de...
45 2017-09-21 16:34:23.641 2017-09-21T16_34_23Z_PT45M38S_Running.csv 10.592581 11.908545 45.635200 1048.000 48.846442 2.335671 Jardin du Luxembourg, Cour de Jonction, Odéon,...
41 2017-09-19 16:36:08.981 2017-09-19T16_36_08Z_PT44M32S_Running.csv 9.041560 12.643044 44.544367 897.000 48.846427 2.335698 Jardin du Luxembourg, Cour de Jonction, Odéon,...
5 2017-09-16 07:17:00.070 2017-09-16T07_17_00Z_PT1H30M8S_Running.csv 17.096634 11.390383 90.146483 1854.000 48.784790 2.291165 Rue François Moreau, Fontenay-aux-Roses, Anton...
6 2017-09-14 17:23:15.896 2017-09-14T16_20_43Z_PT1H42M47S_Biking,Running... 8.048995 11.910404 36.919733 848.000 48.822385 2.338098 Le Petit Train, Allée du Bardo, Montsouris, Pa...
37 2017-09-12 16:59:14.957 2017-09-12T16_59_14Z_PT51M33S_Running.csv 9.248593 12.426092 51.559717 909.000 48.846306 2.335477 Anne de Beaujeu, Cour de la Présidence, Odéon,...
50 2017-09-09 08:27:03.960 2017-09-09T08_27_03Z_PT1H55M7S_Running.csv 21.728122 11.392283 115.132050 2317.000 48.779607 2.291531 Fontenay-Houdan, Rue de Fontenay, Sceaux, Anto...
24 2017-09-07 17:01:55.000 RunnerUp_0058.csv 8.679763 12.729851 41.800000 853.000 48.846475 2.335826 Jardin du Luxembourg, Cour de Jonction, Odéon,...
47 2017-09-05 17:06:22.000 RunnerUp_0057.csv 8.958269 12.844046 41.433333 822.000 48.846517 2.335812 Jardin du Luxembourg, Cour de Jonction, Odéon,...
21 2017-09-04 17:38:54.000 RunnerUp_0056.csv 3.398560 11.900422 17.116667 301.000 48.844327 2.335079 15, Rue Auguste Comte, Odéon, 6e, Paris, Île-d...
38 2017-09-02 08:52:00.450 2017-09-02T08_52_00Z_PT1H58M34S_Running.csv 21.516255 8.859990 121.576833 1717.000 48.777818 2.290877 EHPAD Résidence Renaudin, Passage Marguerite R...
27 2017-09-01 05:07:50.590 2017-09-01T05_07_50Z_PT50M7S_Running.csv 8.090000 10.900000 44.500000 130.000 48.842785 2.329997 Starbucks Coffee, Rue Jules Chaplain, ND-des-C...
15 2017-08-30 17:20:06.174 Cristian_Perez_2017-08-30_19-20-05.csv 8.146645 11.694941 41.716667 121.772 48.846472 2.335846 Jardin du Luxembourg, Cour de Jonction, Odéon,...
43 2017-08-29 17:15:33.209 Cristian_Perez_2017-08-29_19-15-32.csv 8.462380 11.721614 42.616667 164.441 48.846504 2.335784 Jardin du Luxembourg, Cour de Jonction, Odéon,...
32 2017-08-26 08:07:54.000 RunnerUp_0051.csv 23.109283 10.833283 122.233333 2713.000 48.778201 2.291200 EHPAD Résidence Renaudin, Passage Marguerite R...
54 2017-08-23 17:28:48.000 RunnerUp_0050.csv 5.046360 12.262504 24.100000 515.000 48.846125 2.335200 Théâtre du Luxembourg, Rue Auguste Comte, Odéo...
28 2017-08-22 17:48:37.000 RunnerUp_0049.csv 7.042143 11.952149 33.416667 825.000 48.846353 2.335627 Anne de Beaujeu, Cour de la Présidence, Odéon,...
39 2017-08-21 17:50:10.000 RunnerUp_0048.csv 7.073655 12.216654 32.850000 801.000 48.846266 2.335489 Anne de Beaujeu, Cour de la Présidence, Odéon,...
11 2017-08-19 08:43:04.000 RunnerUp_0047.csv 17.425455 11.227346 89.066667 1879.000 48.785283 2.290892 Rue François Moreau, Fontenay-aux-Roses, Anton...
22 2017-08-17 18:03:58.000 RunnerUp_0046.csv 5.329528 12.031507 25.083333 581.000 48.846002 2.335284 Théâtre du Luxembourg, Rue Auguste Comte, Odéo...
25 2017-08-16 17:46:09.000 RunnerUp_0044.csv 7.007194 12.314706 32.766667 774.000 48.846335 2.335589 Anne de Beaujeu, Cour de la Présidence, Odéon,...
55 2017-08-14 10:08:22.000 RunnerUp_43.csv 6.288584 11.746766 30.150000 654.000 48.822337 2.338085 Le Petit Train, Allée du Bardo, Montsouris, Pa...
4 2017-08-12 08:00:36.000 RunnerUp_0042.csv 20.083537 10.992925 97.766667 2349.000 48.782023 2.290309 16, Boulevard Desgranges, Sceaux, Antony, Haut...
13 2017-08-10 18:25:48.000 RunnerUp_0040.csv 5.048189 11.765151 25.500000 470.000 48.846094 2.335153 Théâtre du Luxembourg, Rue Auguste Comte, Odéo...
0 2017-08-08 18:01:53.000 RunnerUp_0038.csv 5.364445 11.557867 26.633333 609.000 48.846072 2.335317 Théâtre du Luxembourg, Rue Auguste Comte, Odéo...
34 2017-08-06 10:10:35.000 RunnerUp_0037.csv 7.722241 11.964914 36.833333 801.000 48.846405 2.335812 Jardin du Luxembourg, Cour de Jonction, Odéon,...
35 2017-08-03 17:59:08.000 RunnerUp_0036.csv 5.534886 11.573736 27.000000 639.000 48.846058 2.335346 Poste des surveillants du jardin, Place André ...
14 2017-07-30 09:42:55.000 RunnerUp_0035.csv 7.526653 11.697312 36.283333 894.000 48.846395 2.335657 Anne de Beaujeu, Cour de la Présidence, Odéon,...
30 2017-07-27 18:20:01.000 RunnerUp_0034.csv 5.841380 11.599974 29.850000 628.000 48.845605 2.335139 Comtesse de Ségur, Rue Auguste Comte, Odéon, 6...
46 2017-07-25 19:50:41.000 RunnerUp_0033.csv 5.027124 11.628791 22.233333 633.000 48.846215 2.335679 Anne de Beaujeu, Cour de la Présidence, Odéon,...
23 2017-07-24 20:54:20.000 RunnerUp_0032.csv 4.530297 11.905375 21.183333 443.000 48.846382 2.335684 Anne de Beaujeu, Cour de la Présidence, Odéon,...
12 2017-07-19 19:55:02.000 RunnerUp_31.csv 4.006633 11.753229 19.050000 537.000 48.849479 2.332601 Sœur, Rue Honoré Chevalier, Odéon, 6e, Paris, ...
48 2017-07-18 20:14:04.000 RunnerUp_0030.csv 4.014472 11.086862 26.450000 486.000 48.844326 2.334989 15, Rue Auguste Comte, Odéon, 6e, Paris, Île-d...
42 2017-07-11 18:09:12.000 RunnerUp_0029.csv 5.035661 11.444715 25.900000 495.000 48.846123 2.335252 Théâtre du Luxembourg, Rue Auguste Comte, Odéo...
2 2017-07-10 18:30:43.000 RunnerUp_0028.csv 5.086652 11.832552 24.866667 528.000 48.846127 2.335270 Théâtre du Luxembourg, Rue Auguste Comte, Odéo...
16 2017-07-09 09:53:50.000 RunnerUp_0027.csv 8.109093 11.397367 37.083333 817.000 48.846400 2.335600 Anne de Beaujeu, Cour de la Présidence, Odéon,...
52 2017-07-06 18:12:50.000 RunnerUp_0026.csv 4.665151 9.431150 30.233333 631.000 48.843965 2.333494 57b, Rue d'Assas, Odéon, 6e, Paris, Île-de-Fra...
29 2017-07-05 18:35:48.000 RunnerUp_0025.csv 5.030024 11.446046 24.616667 521.000 48.846461 2.335721 Jardin du Luxembourg, Cour de Jonction, Odéon,...
17 2017-07-04 17:42:55.000 RunnerUp_24.csv 5.209022 11.345380 27.383333 513.000 48.846047 2.335238 Théâtre du Luxembourg, Rue Auguste Comte, Odéo...
7 2017-06-18 09:39:15.000 RunnerUp_0023.csv 5.019963 10.748088 27.833333 547.000 48.846146 2.335195 Théâtre du Luxembourg, Rue Auguste Comte, Odéo...
49 2017-05-28 10:27:13.000 RunnerUp_22.csv 5.021169 11.038293 26.450000 571.000 48.846203 2.335309 Théâtre du Luxembourg, Rue Auguste Comte, Odéo...
51 2017-05-21 09:57:30.000 RunnerUp_0021.csv 5.031971 11.359628 25.750000 527.000 48.846216 2.335359 Blanche de Castille, Cour de la Présidence, Od...
10 2017-04-30 09:52:48.000 RunnerUp_0020.csv 5.017558 11.314596 25.783333 554.000 48.846171 2.335251 Théâtre du Luxembourg, Rue Auguste Comte, Odéo...
44 2017-04-17 11:01:08.000 RunnerUp_0019.csv 5.012422 11.671251 24.950000 510.000 48.846221 2.335243 Théâtre du Luxembourg, Rue Auguste Comte, Odéo...
8 2017-04-16 10:38:27.000 RunnerUp_0018.csv 4.602083 11.295570 23.600000 470.000 48.846213 2.335456 Anne de Beaujeu, Cour de la Présidence, Odéon,...
40 2017-03-26 11:59:32.000 RunnerUp_0017.csv 5.688288 11.581280 34.716667 577.000 48.845600 2.335287 Pierre Mendès France, Rue Auguste Comte, Odéon...
20 2017-03-25 10:01:18.000 RunnerUp_0016.csv 4.629997 11.634636 23.100000 459.000 48.846481 2.335620 Blanche de Castille, Cour de la Présidence, Od...
26 2016-10-08 05:20:17.000 RunnerUp_10.csv 15.028409 8.991190 100.200000 1486.000 36.450690 25.415905 Θήρα - Οία, Φοινικιά, Δήμος Θήρας, Περιφερειακ...
18 2016-10-04 09:45:14.000 RunnerUp_0007.csv 0.005205 6.246022 0.050000 4.000 48.725136 2.145281 458, Avenue des Accélérateurs, CEA Saclay, Sai...
36 2016-10-02 09:31:51.000 RunnerUp_0006.csv 7.001115 11.774183 34.916667 655.000 48.846376 2.335594 Anne de Beaujeu, Cour de la Présidence, Odéon,...
9 2016-10-01 08:02:18.000 RunnerUp_0005.csv 4.008485 11.110023 20.733333 481.000 48.846831 2.336178 Jardin du Luxembourg, Cour de Jonction, Odéon,...
19 2016-09-13 19:59:11.000 RunnerUp_0004.csv 2.004824 10.999175 10.866667 153.000 43.601009 3.897712 Banque Populaire, Rue de Syracuse, Port Marian...
33 2016-09-13 19:49:33.000 RunnerUp_0002.csv 1.037511 11.742230 5.150000 111.000 43.607851 3.889808 Hortus, 38, Place du Millénaire, Antigone, Cen...
3 2016-09-10 06:16:10.000 RunnerUp_0001.csv 4.040153 10.275758 23.133333 409.000 48.845935 2.335594 Poste des surveillants du jardin, Place André ...
In [7]:
recent_frame = frame[frame['Date'] > pd.datetime(2017, 6, 1)]

Kilometers by date

In [81]:
recent_frame = recent_frame.assign(Month=recent_frame['Date'].dt.month, Week=recent_frame['Date'].dt.week, 
                                   Weekday=recent_frame['Date'].dt.weekday)
In [78]:
months = ['June', 'July', 'August', 'Sept']
fig, axr = plt.subplots(1,3, figsize=(14,5))
axr[0].bar(recent_frame.groupby(recent_frame.Date.dt.month).agg({'Kilometers': 'sum'}).index, 
        recent_frame.groupby(recent_frame.Date.dt.month).agg({'Kilometers': 'sum'}).values,
        yerr=recent_frame.groupby(recent_frame.Date.dt.month).agg({'Kilometers': 'std'}).values,
        tick_label=months, label='Number of kilometers')
axr[0].set_title('Total number of kilometers')
axr[0].set_ylabel('Km')
recent_frame.boxplot(['Speed'], by='Month', ax=axr[1])
axr[1].set_xticklabels(months)
axr[1].set_ylabel('Km/h')
recent_frame.groupby('Month')['Speed'].count().plot.bar(ax=axr[2], color='C1')
axr[2].set_xticklabels(months)
axr[2].set_title('Number of trainings')
plt.show()
In [93]:
months = ['June', 'July', 'August', 'Sept']
fig, axr = plt.subplots(3, figsize=(14,8), sharex=True)
recent_frame.groupby('Week')['Kilometers'].sum().plot.bar(ax=axr[0])
axr[0].set_title('Total number of kilometers')
axr[0].set_ylabel('Km')
recent_frame.boxplot(['Speed'], by='Week', ax=axr[1])
axr[1].set_ylabel('Km/h')
recent_frame.groupby('Week')['Speed'].count().plot.bar(ax=axr[2], color='C1')
axr[2].set_title('Number of trainings')
plt.show()
In [118]:
weekdays = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
fig, axr = plt.subplots(3, figsize=(14,8))
recent_frame.groupby('Weekday')['Kilometers'].sum().plot.area(ax=axr[0])
axr[0].set_title('Total number of kilometers')
axr[0].set_ylabel('Km')
axr[0].set_xticklabels(weekdays)
recent_frame.boxplot(['Speed'], by='Weekday', ax=axr[1])
axr[1].set_ylabel('Km/h')
axr[1].set_xticklabels(weekdays)
recent_frame.groupby('Weekday')['Speed'].count().plot.area(ax=axr[2], color='C1')
axr[2].set_title('Number of trainings')
axr[2].set_xticklabels(weekdays)
plt.show()

Marathon prediction

In [119]:
from sklearn import datasets, linear_model
from sklearn.metrics import mean_squared_error, r2_score
In [120]:
recent_frame[['Kilometers', 'Climb']].values.shape
Out[120]:
(42, 2)
In [121]:
np.stack([recent_frame.index.values,recent_frame['Time'].values, recent_frame['Climb'].values], axis=1).shape
Out[121]:
(42, 3)
In [122]:
#X_train = np.stack([recent_frame.index.values, recent_frame['Kilometers'].values, recent_frame['Climb'].values ], axis=1)
X_train = recent_frame[['Kilometers','Climb']].values
y_train = recent_frame['Time']
X_test = np.array([42.195, 400]).reshape(1,-1)
In [123]:
regr = linear_model.LinearRegression()
regr.fit(X_train, y_train)
y_pred = regr.predict(X_test)
print('Distance: {} Km, Speed: {} Km/h, Time: {} hours \n'.format(X_test[0][0], X_test[0][0]/float(y_pred[0]/60), y_pred[0]/60))
Distance: 42.195 Km, Speed: 10.563563454086022 Km/h, Time: 3.99439073598586 hours 

In [124]:
Dis = 10
Climb = 400
val = np.array([Dis, Climb]).reshape(1,-1)
print(Dis/(regr.predict(val)/60))
#print('Distance: {} Km, Speed: {} Km/h, Time: {} hours \n'.format(X_test[0][1], X_test[0][1]/float(y_pred[0]/60), y_pred[0]/60))
[ 11.210528]
In [221]:
plt.figure(figsize=(15,4))
plt.scatter(X_train[:,0], regr.predict(X_train)/60)
plt.scatter(X_test[:,0], y_pred/60)
plt.plot([0, X_test[:,0]], [0, y_pred/60], '--', color='C2')
plt.ylabel('Hours')
plt.xlabel('Kilometers')
plt.show()

Speed by training

In [223]:
plt.figure(figsize=(15,4))
ax = plt.axes()
ax.set_xlim([pd.datetime(2017,6,15),pd.datetime(2017,10,10)])

legend_sizes = np.sort(recent_frame.Climb)[::len(recent_frame.Climb)//4][-3:]
# get the indices for each of the legend sizes
indices = [np.where(recent_frame.Climb==v)[0][0] for v in legend_sizes]
# plot each point again, and its value as a label
for i in indices:
    plt.scatter(x=recent_frame.Date.iloc[i], y=recent_frame.Speed.iloc[i], c=recent_frame.Kilometers.iloc[i], s=recent_frame.Climb.iloc[i]/2,
                  vmin=0,vmax=1,edgecolors='none',
                  label='{:.2f}'.format(recent_frame.Climb.iloc[i]))
# add the legend
plt.scatter(x=recent_frame.Date.values, y=recent_frame.Speed, c=recent_frame.Kilometers, s=recent_frame.Climb, label=None)
#plt.scatter(x=pd.to_datetime('2017-10-09', format='%Y-%m-%d'), y=X_test[0][0]/float(y_pred[0]/60), c=X_test[0][0], s=X_test[0][1], linewidth=3)
plt.plot(X_test[0][0]/float(y_pred[0]/60))
plt.colorbar(label='Distance')
plt.xlabel('Date')
plt.ylabel('Average Speed')
plt.legend(scatterpoints=1, title='Climb', labelspacing=1.2)
plt.show()
In [261]:
list_speed_bubble = list()
list_speed_prediction = list()
list_linear_regression = list()
for k,val in recent_frame.iterrows():
    list_speed_bubble.append({'x': val['Date'].strftime("%Y-%m-%d"), 'y': np.round(val['Speed'],2), 'r': np.round(val['Kilometers'],2)})
    to_predict = val[['Kilometers', 'Climb']].values.reshape(1,-1)
    list_linear_regression.append({'x': np.round(val['Kilometers'],2), 'y': np.round(regr.predict(to_predict)[0]/60,2)})
    #list_speed_prediction.append({'x': val['Date'].strftime("%Y-%m-%d"), 'y': np.round(val['Kilometers']/(regr.predict(to_predict)[0]/60),2), 'r': np.round(val['Kilometers'],2)})

list_speed_bubble.append({'x': '2017-10-08', 'y': np.round(X_test[0][0]/float(y_pred[0]/60),2), 'r': np.round(X_test[0][0],2)})
list_speed_prediction.append({'x': '2017-10-08', 'y': np.round(X_test[0][0]/float(y_pred[0]/60),2), 'r': np.round(X_test[0][0],2)})
In [262]:
to_predict = np.reshape([0,40], (1,-1))
regr.predict(to_predict)[0]/60
#list_speed_predi
Out[262]:
-0.048497971407600253

Export json

In [263]:
df_steps = pd.concat([recent_frame.Date.dt.strftime("%s"), recent_frame.Kilometers.round(1)], axis=1)

dic_steps = dict()
for k,x in df_steps.iterrows():
    dic_steps[x['Date']] = x['Kilometers']
In [264]:
with open('output/marathon.json', 'w') as outfile:
    json.dump({'weekday': {'Kilometers': [i[0] for i in recent_frame.groupby(recent_frame.Date.dt.weekday).agg({'Kilometers': 'mean'}).round(1).values.tolist()],
                           'Speed': [i[0] for i in recent_frame.groupby(recent_frame.Date.dt.weekday).agg({'Speed': 'mean'}).round(1).values.tolist()],
                           'Trains': [i[0] for i in recent_frame.groupby(recent_frame.Date.dt.weekday).agg({'Kilometers': 'count'}).round(1).values.tolist()],
                           'index' : weekdays
                          },
               'week': {'index' : [float(i) for i in recent_frame.groupby(recent_frame.Date.dt.week).agg({'Kilometers': 'count'}).index.tolist()],
                       'Kilometers': [float(i[0]) for i in recent_frame.groupby(recent_frame.Date.dt.week).agg({'Kilometers': 'sum'}).round(1).values],
                       'Speed': [float(i[0]) for i in recent_frame.groupby(recent_frame.Date.dt.week).agg({'Speed': 'mean'}).round(1).values],
                       'Trains': [float(i[0]) for i in recent_frame.groupby(recent_frame.Date.dt.week).agg({'Kilometers': 'count'}).round(1).values]
                       },
               'month': {'Kilometers' : [float(i) for i in recent_frame.groupby(recent_frame.Date.dt.month).agg({'Kilometers': 'sum'}).round(1).values],
                         'Speed' : [float(i) for i in recent_frame.groupby(recent_frame.Date.dt.month).agg({'Speed': 'mean'}).round(1).values],
                         'Trains' : [float(i) for i in recent_frame.groupby(recent_frame.Date.dt.month).agg({'Kilometers': 'count'}).round(1).values],
                         'index' : months
               },
               'heatmap_km': dic_steps,
               'bubble_speed': {'real': list_speed_bubble, 'predict': sorted(list_speed_prediction, key=lambda x : x['x'], reverse=False)},
               'linear_reg': {'points': list_linear_regression, 'line': [{'x': 0, 'y': -0.04}, {'x':  X_test[:,0][0], 'y' : np.round((y_pred/60)[0], 2)}]}
               #'leaflet': [[i[0], i[1], 1] for i in [[float(v.Lat), float(v.Long)] for k,v in recent_frame.iterrows()]],
              }, outfile, indent=1)

Heatmap folium

In [254]:
mean_lat = np.mean([i[0] for i in [[float(v.Lat), float(v.Long)] for k,v in recent_frame.iterrows()]])
mean_long = np.mean([i[1] for i in [[float(v.Lat), float(v.Long)] for k,v in recent_frame.iterrows()]])
m = folium.Map(location=[mean_lat, mean_long ], zoom_start=11, tiles='OpenStreetMap')
m.add_child(plugins.HeatMap(recent_frame[['Lat','Long']].values, radius = 20), name='Training location')
colormap = cm.LinearColormap(['blue', 'green',  'yellow', 'orange', 'red'],  index=[0, 0.25, 0.5, 0.75, 1.0]).scale(0,20)
colormap.caption = 'Number of trainings'
m.add_child(colormap)
m
Out[254]:
In [ ]:
 
In [ ]: