https://github.com/BMClab/covid19
Laboratory of Biomechanics and Motor Control
Federal University of ABC, Brazil
The data used in this Jupyter notebook are available on the Figshare repository https://doi.org/10.6084/m9.figshare.16620238.
from pathlib import Path
import pickle
import numpy as np
import scipy as sp
import pandas as pd
import seaborn as sns
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
import matplotlib.patches as patches
from tqdm.notebook import tqdm
%load_ext watermark
path2 = Path(r'./../data/')
country = ['Brazil', 'br']
country = ['all countries', 'all']
load_results = True # load file with results if exists
if not load_results:
# Warning: the bootstrap process takes hours!
from bootstrap_stat import bootstrap_stat as bp
tqdm.pandas(desc='Boot', leave=False)
pd.set_option('display.precision', 3)
plt.rcParams.update({'font.size': 14, 'xtick.labelsize': 12,
'ytick.labelsize': 12})
sns.set_style('whitegrid', rc={'xtick.bottom': True, 'xtick.top': True,
'ytick.left': True,
'ytick.right': True, 'xtick.direction': 'in',
'ytick.direction': 'in'})
Slice = pd.IndexSlice
# Set of colors that is unambiguous both to colorblinds and non-colorblinds
# https://www.cta-observatory.org/wp-content/uploads/2020/10/CTA_ColourBlindness_BestPractices-1.pdf
# https://jfly.uni-koeln.de/color/index.html
#matplotlib.style.use('seaborn-colorblind')
matplotlib.style.use('tableau-colorblind10')
colors = sns.color_palette()
display(colors)
colorbase = 'k'
color2019 = colors[0]
color2020 = colors[1]
colorn = colors[5]
colorvar = colors[4]
colorind = colors[6]
# Statistics
alpha = 0.05
two_tailed = True
# confidence interval
estimate = np.mean
boot = 100000 # number of bootstrap samples
seed = 0
# other variables:
years = ['2019', '2020']
quarters = ['First', 'Second', 'Third', 'Fourth']
months = ['January', 'February', 'March', 'April', 'May', 'June', 'July',
'August', 'September', 'October', 'November', 'December']
freqs = ['d', 'w', 'm', 'q']
freqs_s = ['day', 'week', 'month', 'quarter']
# feature (dependent variable)
variables, units = ['distance', 'duration'], ['km', 'min']
vars_d = [v + '_d' for v in variables]
# period for analysis
freq, freq_s = freqs[1], freqs_s[1]
%watermark
%watermark --iversions
Last updated: 2022-03-12T01:10:26.186979-03:00 Python implementation: CPython Python version : 3.9.10 IPython version : 7.32.0 Compiler : GCC 9.4.0 OS : Linux Release : 5.13.0-30-generic Machine : x86_64 Processor : x86_64 CPU cores : 12 Architecture: 64bit pandas : 1.4.1 numpy : 1.22.3 scipy : 1.8.0 seaborn : 0.11.2 matplotlib : 3.5.1 bootstrap_stat: 0.2.4.2 json : 2.0.9
# standardization (mean 0, variance 1)
stdz = lambda x: (x-x.mean())/x.std()
def normality(x):
"""Kurtosis, skewness, p-value of normality test using the scipy library.
"""
return [sp.stats.kurtosis(x), sp.stats.skew(x), sp.stats.normaltest(x).pvalue]
def cohensd(x):
"""Cohen's d effect size for within-subject sample.
"""
return np.abs(np.mean(x, axis=0)) / np.std(x, axis=0, ddof=1)
def ci_asl(y, stat=np.nanmean, alpha2=0.025, boot=boot):
"""Confidence interval and 'pvalue' of hypothesis testing by bootstrap.
Parameters
----------
y : 1-d array_like
Calculate the confidence interval of these values.
stat : function (optional, default=np.nanmean)
Statistics (a function) to which the confidence interval will be
estimated
alpha : float (optional, default=0.025)
alpha level (]0, 1[) of the confidence interval
boot : int (optional, default=100000)
Number of bootstrap iteractions
Returns
-------
[ci_low, ci_high, asl] : list of floats
Lower and upper bounds on a 100(1-2*`alpha`)% confidence interval on
stat of `y`.
Achieved significance level, the probability of an outcome at least as
extreme as that actually observed under the null hypothesis; the p-value.
See Also
--------
https://github.com/rwilson4/bootstrap-stat
"""
ed = bp.EmpiricalDistribution(y)
ci_low, ci_high, theta_star = bp.percentile_interval(ed, stat, alpha=alpha2, B=boot,
return_samples=True, num_threads=-1)
asl = bp.percentile_asl(ed, stat, y, theta_0=0, B=boot,
theta_star=theta_star, two_sided=True, num_threads=1)
return [ci_low, ci_high, asl]
def describe(y, variable=['distance_d', 'duration_d'],
new_variable=None, show=True):
"""Descriptive statistics for dataframe columns.
"""
ys = []
stat = ['count', 'mean', 'std', cohensd]
for var in variable:
y1 = y[['athlete', var]
].pivot(columns='athlete')[var].T.agg(stat, axis=0).transpose()
y2 = y[['athlete', var]
].pivot(columns='athlete')[var].T.progress_apply(ci_asl, alpha2=alpha/2
).transpose()
y2.rename(columns={0: 'ci_inf', 1: 'ci_sup', 2: 'pvalue'}, inplace=True)
ys.append(pd.concat([y1, y2], axis=1))
if new_variable is None:
new_variable = variable
ys = pd.concat(ys, axis=1, keys=new_variable)
ys.index = ys.index.dayofyear # range(ys.shape[0])
# correct index when joining leap year and non leap year
if ys.shape[0] == 365:
ys.index = range(1, 366, 1)
elif ys.shape[0] == 52:
ys.index = range(1, 365, 7)
ys.index.rename('Period', inplace=True)
if show:
display(ys)
return ys
def highlight_cohensd(x):
'''
Set background color for cohensd values.
'''
#['Nothing', 'Very small', 'Small', 'Medium', 'Large', 'Very large', 'Huge']
d = [0, .01, .2, .5, .8, 1.2, 2, 100]
# colors
cm = sns.color_palette('Greens', n_colors=len(d)-2).as_hex()
cm = ['background-color: {};font-weight:bold;'.format(c) for c in cm]
cm.insert(0, 'background-color: '';')
x = pd.cut(x, bins=d, right=False, labels=cm, retbins=False)
return x.to_list()
def highlight_pvalue(x, level=alpha,
props='color:white;background-color:red;font-weight:bold'):
return np.where(x <= level, props, '')
def highlight_max(x,
props='color:white;background-color:blue;font-weight:bold'):
return np.where(x == np.nanmax(x.values), props, '')
def highlight_min(x,
props='color:white;background-color:purple;font-weight:bold'):
return np.where(x == np.nanmin(x.values), props, '')
def display_df(df, subset='mean'):
"""Diplay dataframe with a certain style.
"""
if type(df.index) == pd.DatetimeIndex:
df.index = df.index.strftime('%Y-%m-%d')
display(df.style
.highlight_max(subset=subset,
props='color:white;font-weight:bold;background-color:blue;')
.highlight_min(subset=subset,
props='color:white;font-weight:bold;background-color:purple;'))
def display_dfsd(df, title=''):
"""Display dataframe with certain style.
See https://pandas.pydata.org/pandas-docs/stable/user_guide/style.html
"""
Slice = pd.IndexSlice
display(df.style.format('{:.0f}', subset=Slice[:, Slice[:, 'count']])
.format('{:.4f}', subset=Slice[:, Slice[:, 'pvalue']])
.highlight_max(subset=Slice[:, Slice[:, 'mean']],
props='color:white;font-weight:bold;background-color:blue;')
.highlight_min(subset=Slice[:, Slice[:, 'mean']],
props='color:white;font-weight:bold;background-color:purple;')
.apply(highlight_cohensd, subset=Slice[:, Slice[:, 'cohensd']])
.apply(highlight_pvalue, level=alphaS, subset=Slice[:, Slice[:, 'pvalue']])
.set_caption(title)
.set_table_styles([{'selector': 'caption', 'props': 'font-weight:bold; ' +
'text-align: center; ' +
'caption-side: top; color: #000000; font-size:1.4em;'
}]))
dfs, dfs_no0, nathletes, nruns = dict(), dict(), dict(), dict()
print('Country: {}'. format(country[0]))
for year in years:
for f, frq in enumerate(freqs):
# load dataset and select country from start to speedup process
fname = path2 / 'run_ww_{}_{}.parquet'.format(year, frq)
df = pd.read_parquet(fname, columns=['datetime', 'athlete', 'distance',
'duration', 'country'])
if country[1] != 'all':
df = df[df['country'] == country[0]]
df = df.set_index('datetime', drop=True)
#df.index = df.index.normalize()
# correct dates
if df.index[0].is_leap_year and frq == 'd':
# if leap year, remove Feb 29, average data of Feb 28 and 29
feb28 = pd.Timestamp(unit='D', year=df.index[0].year, month=2, day=28)
feb29 = pd.Timestamp(unit='D', year=df.index[0].year, month=2, day=29)
nbs = df.select_dtypes(include='number').columns.to_list()
df.loc[df.index==feb28, nbs] = (df.loc[df.index==feb28, nbs].values +
df.loc[df.index==feb29, nbs].values)/2
df = df.drop(index=feb29)
display(df.iloc[[0, -1]].style.set_caption(
'Year: {}, Frequency: {} (first and last rows)'.format(year, freqs_s[f])))
# create dictionary will all the data (including no runs data)
dfs[year, frq] = df
# create dictionary will all the data (excluding no runs data)
dfs_no0[year, frq] = df[df[variables[0]] > 0]
# number of athletes and running activities
nathletes[year, frq] = dfs_no0[year, frq].groupby(level='datetime').size()
x = dfs_no0[year, frq].groupby('athlete').size()
nruns[year, frq] = x[x > 0] # removes athletes with zero runs
Country: all countries
athlete | distance | duration | country | |
---|---|---|---|---|
datetime | ||||
2019-01-01 00:00:00 | 0 | 0.000000 | 0.000000 | United States |
2019-12-31 00:00:00 | 37598 | 25.670000 | 223.000000 | China |
athlete | distance | duration | country | |
---|---|---|---|---|
datetime | ||||
2019-01-01 00:00:00 | 0 | 0.000000 | 0.000000 | United States |
2019-12-24 00:00:00 | 37598 | 46.077500 | 322.947917 | China |
athlete | distance | duration | country | |
---|---|---|---|---|
datetime | ||||
2019-01-31 00:00:00 | 0 | 0.000000 | 0.000000 | United States |
2019-12-31 00:00:00 | 37598 | 297.745161 | 2378.951613 | China |
athlete | distance | duration | country | |
---|---|---|---|---|
datetime | ||||
2019-03-31 00:00:00 | 0 | 0.000000 | 0.000000 | United States |
2019-12-31 00:00:00 | 37598 | 1206.590000 | 8937.600000 | China |
athlete | distance | duration | country | |
---|---|---|---|---|
datetime | ||||
2020-01-01 00:00:00 | 0 | 0.000000 | 0.000000 | United States |
2020-12-31 00:00:00 | 37598 | 10.620000 | 71.000000 | China |
athlete | distance | duration | country | |
---|---|---|---|---|
datetime | ||||
2020-01-01 00:00:00 | 0 | 0.000000 | 0.000000 | United States |
2020-12-23 00:00:00 | 37598 | 102.052222 | 847.220370 | China |
athlete | distance | duration | country | |
---|---|---|---|---|
datetime | ||||
2020-01-31 00:00:00 | 0 | 0.000000 | 0.000000 | United States |
2020-12-31 00:00:00 | 37598 | 377.719355 | 2842.564516 | China |
athlete | distance | duration | country | |
---|---|---|---|---|
datetime | ||||
2020-03-31 00:00:00 | 0 | 34.040000 | 180.166667 | United States |
2020-12-31 00:00:00 | 37598 | 1096.760000 | 7969.533333 | China |
dfs['2019', 'd'].info(memory_usage='deep')
<class 'pandas.core.frame.DataFrame'> DatetimeIndex: 13290380 entries, 2019-01-01 to 2019-12-31 Data columns (total 4 columns): # Column Dtype --- ------ ----- 0 athlete category 1 distance float64 2 duration float64 3 country category dtypes: category(2), float64(2) memory usage: 381.5 MB
dfs['2019', freq]
athlete | distance | duration | country | |
---|---|---|---|---|
datetime | ||||
2019-01-01 | 0 | 0.000 | 0.000 | United States |
2019-01-01 | 1 | 5.270 | 30.200 | Germany |
2019-01-01 | 2 | 9.300 | 98.000 | United Kingdom |
2019-01-01 | 3 | 103.130 | 453.400 | United Kingdom |
2019-01-01 | 4 | 34.670 | 185.650 | United States |
... | ... | ... | ... | ... |
2019-12-24 | 37594 | 12.835 | 63.481 | United Kingdom |
2019-12-24 | 37595 | 151.725 | 623.919 | United States |
2019-12-24 | 37596 | 35.770 | 153.081 | United States |
2019-12-24 | 37597 | 31.938 | 176.473 | United States |
2019-12-24 | 37598 | 46.078 | 322.948 | China |
1893424 rows × 4 columns
dfs['2020', freq]
athlete | distance | duration | country | |
---|---|---|---|---|
datetime | ||||
2020-01-01 | 0 | 0.000 | 0.000 | United States |
2020-01-01 | 1 | 70.330 | 394.200 | Germany |
2020-01-01 | 2 | 14.650 | 79.067 | United Kingdom |
2020-01-01 | 3 | 41.410 | 195.667 | United Kingdom |
2020-01-01 | 4 | 41.340 | 209.100 | United States |
... | ... | ... | ... | ... |
2020-12-23 | 37594 | 128.154 | 572.587 | United Kingdom |
2020-12-23 | 37595 | 20.051 | 87.461 | United States |
2020-12-23 | 37596 | 144.636 | 625.774 | United States |
2020-12-23 | 37597 | 0.000 | 0.000 | United States |
2020-12-23 | 37598 | 102.052 | 847.220 | China |
1893424 rows × 4 columns
if country[1] == 'all':
# Covid-19 stringency index averaged by percentage of athletes' countries
c19idx = pd.read_csv(path2 / 'policy_response_indexes.csv',
sep=',', header=0, parse_dates=['date'], verbose=False)
else:
# Covid-19 stringency index of each country
c19idx = pd.read_csv(path2 / 'policy_response_indexes_countries.csv',
sep=',', header=0, parse_dates=['date'], verbose=False)
c19idx = c19idx[c19idx['country'] == country[0]].drop(columns='country')
c19idx = c19idx.set_index('date', drop=True)
def correct_date(y, freq):
"""
Correct dates and adjust data of last days to avoid last week with < 7 days
or of the last day of February if leap year.
"""
# numerical columns
cols_num = y.select_dtypes(include='number').columns.to_list()
ndays_lastweek = 7 + y.index[-1].dayofyear % 7
if freq == '7d' and ndays_lastweek > 7:
ts = pd.Timestamp(y.index[-1].date() - pd.to_timedelta(ndays_lastweek-7, unit='D'))
y.index = y.index.where(y.index <= ts, ts)
grouper = pd.Grouper(axis=0, freq=freq)
y = y.groupby(grouper).mean()
# correct the divisor if the last week doesn't have 7 days
y.loc[y.index[-1], cols_num] = y.loc[y.index[-1], cols_num] * (7 / ndays_lastweek)
elif freq == 'd' and y.index.unique()[59].day == 29: # leap year
grouper = pd.Grouper(axis=0, freq=freq)
y = y.groupby(grouper).mean()
# February 28 as the average February 28 and 29
y.loc[y.index[58], cols_num] = y.loc[y.index[58:60], cols_num].mean(axis=0)
y = y.drop(index=y.index[59])
elif freq == 'm' and y.index.unique()[59].day == 29: # just resample data
grouper = pd.Grouper(axis=0, freq=freq)
y = y.groupby(grouper).mean()
return y
c19idx = correct_date(c19idx, '7d' if freq == 'w' else freq)
c19idx
si | ci | hi | wi | |
---|---|---|---|---|
date | ||||
2020-01-01 | 0.178 | 0.359 | 0.000 | 0.000 |
2020-01-08 | 0.273 | 0.448 | 0.000 | 0.000 |
2020-01-15 | 0.722 | 1.348 | 0.000 | 0.000 |
2020-01-22 | 2.906 | 5.626 | 0.009 | 0.012 |
2020-01-29 | 6.044 | 9.639 | 0.023 | 0.028 |
2020-02-05 | 8.737 | 12.116 | 0.031 | 0.028 |
2020-02-12 | 9.016 | 12.360 | 0.031 | 0.028 |
2020-02-19 | 9.530 | 12.771 | 0.043 | 0.053 |
2020-02-26 | 12.177 | 15.765 | 0.059 | 0.094 |
2020-03-04 | 18.774 | 22.053 | 0.106 | 0.101 |
2020-03-11 | 33.520 | 31.876 | 0.726 | 0.323 |
2020-03-18 | 63.104 | 52.390 | 1.529 | 2.205 |
2020-03-25 | 73.840 | 59.853 | 1.773 | 2.728 |
2020-04-01 | 74.824 | 61.725 | 1.835 | 2.757 |
2020-04-08 | 75.072 | 63.159 | 1.844 | 2.778 |
2020-04-15 | 74.958 | 63.241 | 1.839 | 2.779 |
2020-04-22 | 74.763 | 63.305 | 1.833 | 2.769 |
2020-04-29 | 74.419 | 63.698 | 1.824 | 2.746 |
2020-05-06 | 73.233 | 63.034 | 1.720 | 2.704 |
2020-05-13 | 70.652 | 61.612 | 1.465 | 2.654 |
2020-05-20 | 70.168 | 61.781 | 1.442 | 2.630 |
2020-05-27 | 69.119 | 62.241 | 1.392 | 2.440 |
2020-06-03 | 67.797 | 62.162 | 1.372 | 2.332 |
2020-06-10 | 67.564 | 62.096 | 1.361 | 2.193 |
2020-06-17 | 65.789 | 61.170 | 1.345 | 1.877 |
2020-06-24 | 64.964 | 60.946 | 1.315 | 1.830 |
2020-07-01 | 64.353 | 61.411 | 1.360 | 1.855 |
2020-07-08 | 63.075 | 60.485 | 1.387 | 1.857 |
2020-07-15 | 62.725 | 60.282 | 1.261 | 1.870 |
2020-07-22 | 62.214 | 59.992 | 0.973 | 1.875 |
2020-07-29 | 62.986 | 60.858 | 0.978 | 1.897 |
2020-08-05 | 63.722 | 61.380 | 0.981 | 1.923 |
2020-08-12 | 63.125 | 61.020 | 0.986 | 1.951 |
2020-08-19 | 63.170 | 61.093 | 0.975 | 1.970 |
2020-08-26 | 63.045 | 60.660 | 0.962 | 1.971 |
2020-09-02 | 61.797 | 59.367 | 0.918 | 1.958 |
2020-09-09 | 60.595 | 58.540 | 0.916 | 1.944 |
2020-09-16 | 60.079 | 58.332 | 0.941 | 1.951 |
2020-09-23 | 59.921 | 58.223 | 0.934 | 1.937 |
2020-09-30 | 59.969 | 58.171 | 0.922 | 1.924 |
2020-10-07 | 59.723 | 57.894 | 0.988 | 1.905 |
2020-10-14 | 60.585 | 58.526 | 1.438 | 1.898 |
2020-10-21 | 63.334 | 60.490 | 1.582 | 1.918 |
2020-10-28 | 63.139 | 60.415 | 1.324 | 1.913 |
2020-11-04 | 63.820 | 60.846 | 1.150 | 2.081 |
2020-11-11 | 65.017 | 61.402 | 1.219 | 2.090 |
2020-11-18 | 68.760 | 64.097 | 1.534 | 2.425 |
2020-11-25 | 69.207 | 64.431 | 1.533 | 2.421 |
2020-12-02 | 66.706 | 63.089 | 1.372 | 1.989 |
2020-12-09 | 67.412 | 64.195 | 1.523 | 1.995 |
2020-12-16 | 69.376 | 66.847 | 1.709 | 2.204 |
2020-12-23 | 54.817 | 52.830 | 1.404 | 1.805 |
for year in years:
print('Year: {}'.format(year))
print(' Number of days:', dfs[year, 'd'].index.value_counts().size)
print(' Number of athletes:', nruns[year, 'd'].size)
print(' Number of activities:', dfs[year, 'd'].shape[0])
print(' Number of actual running activities:', nathletes[year, 'd'].sum())
nathlete = nruns['2019', 'd'].size
nactivity = nathletes['2019', 'd'].sum() + nathletes['2020', 'd'].sum()
print('Total number of actual running activities in 2019 and 2020:', nactivity)
Year: 2019 Number of days: 365 Number of athletes: 36412 Number of activities: 13290380 Number of actual running activities: 4677389 Year: 2020 Number of days: 365 Number of athletes: 35083 Number of activities: 13290380 Number of actual running activities: 4575794 Total number of actual running activities in 2019 and 2020: 9253183
print('Median and interquartile range of number of days the athletes ran each year:')
for year in years:
print('In {}: {:.0f} ({:.0f}, {:.0f}) days'.
format(year, *np.percentile(nruns[year, 'd'], [50, 25, 75]).round()))
Median and interquartile range of number of days the athletes ran each year: In 2019: 120 (63, 183) days In 2020: 119 (59, 191) days
fig, axs = plt.subplots(3, 1, squeeze=True, sharex=True, figsize=(12, 7))
for i, year in enumerate(years):
y = nathletes[year, 'd'].values
axs[0].plot(np.linspace(0, 365, 366), np.append(y, y[-1]),
color=colors[i], lw=2, label=year, drawstyle='steps-post')
y = nathletes[year, 'w'].values
axs[1].plot(np.linspace(0, 365, 53), np.append(y, y[-1]),
color=colors[i], lw=3, label=year, drawstyle='steps-post')
x = nathletes[year, 'm'].index.day_of_year.values
y = nathletes[year, 'm'].values
axs[2].plot(np.append([0], x), np.append(y, y[-1]),
color=colors[i], lw=3, label=year, drawstyle='steps-post')
axs[0].set_xlim([0, 365])
axs[0].legend(['2019', '2020'])
axs[0].set_ylabel('Per day')
axs[1].set_ylabel('Per week')
axs[2].set_ylabel('Per month')
axs[2].set_xlabel('Month')
axs[2].set_xticks(np.append([0], x[:-1]))
axs[2].set_xticklabels(months, rotation=0, ha='center')
offset = matplotlib.transforms.ScaledTranslation(34/72, 0, fig.dpi_scale_trans)
for label in axs[2].get_xticklabels():
label.set_transform(label.get_transform() + offset)
for ax in axs:
ax.tick_params(axis='both', which='major', labelsize=13)
plt.suptitle('Number of athletes running per period (out of a total of {:,d})'
.format(nruns['2019', 'd'].size), fontsize=18)
plt.tight_layout(h_pad=.5)
plt.show()
nruns['2019', 'd'].describe()
count 36412.000 mean 128.457 std 81.522 min 1.000 25% 63.000 50% 120.000 75% 183.000 max 365.000 dtype: float64
365 / nruns['2019', 'd'].describe()
count 0.010 mean 2.841 std 4.477 min 365.000 25% 5.794 50% 3.042 75% 1.995 max 1.000 dtype: float64
nruns['2020', 'd'].describe()
count 35083.000 mean 130.428 std 87.492 min 1.000 25% 59.000 50% 119.000 75% 191.000 max 365.000 dtype: float64
365 / nruns['2020', 'd'].describe()
count 0.010 mean 2.798 std 4.172 min 365.000 25% 6.186 50% 3.067 75% 1.911 max 1.000 dtype: float64
print('Parameters:')
print(' years =', years)
print(' frequency =', freq)
print(' variables =', variables)
print(' estimate =', estimate)
Parameters: years = ['2019', '2020'] frequency = w variables = ['distance', 'duration'] estimate = <function mean at 0x7f4ec8101310>
# Statistics for annual data
dfs_stat = dict()
for y in years:
for f in freqs:
idx = pd.Series(data=True, index=dfs[y, f].index)
dfs_stat[y, f] = dfs[y, f][['distance', 'duration']].describe().T
grouper = pd.Grouper(axis=0, freq='y', sort=True)
for year in years:
print(year)
display(dfs[year, freq][['distance', 'duration']
].groupby(grouper).describe().stack(level=0))
display(dfs[year, freq][['distance', 'duration']
].groupby(grouper).sum())
2019
25% | 50% | 75% | count | max | mean | min | std | ||
---|---|---|---|---|---|---|---|---|---|
datetime | |||||||||
2019-12-31 | distance | 1.63 | 21.600 | 46.18 | 1.893e+06 | 711.14 | 29.241 | 0.0 | 30.105 |
duration | 10.75 | 122.917 | 254.55 | 1.893e+06 | 8239.20 | 160.582 | 0.0 | 166.521 |
distance | duration | |
---|---|---|
datetime | ||
2019-12-31 | 5.537e+07 | 3.040e+08 |
2020
25% | 50% | 75% | count | max | mean | min | std | ||
---|---|---|---|---|---|---|---|---|---|
datetime | |||||||||
2020-12-31 | distance | 0.0 | 18.060 | 43.020 | 1.893e+06 | 624.57 | 27.074 | 0.0 | 30.320 |
duration | 0.0 | 103.683 | 239.433 | 1.893e+06 | 6913.00 | 149.858 | 0.0 | 167.785 |
distance | duration | |
---|---|---|
datetime | ||
2020-12-31 | 5.126e+07 | 2.837e+08 |
grouper = pd.Grouper(axis=0, freq='y', sort=True)
for year in years:
print(year)
display(dfs_no0[year, freq][['distance', 'duration']
].groupby(grouper).describe().stack(level=0))
display(dfs_no0[year, freq][['distance', 'duration']
].groupby(grouper).sum())
2019
25% | 50% | 75% | count | max | mean | min | std | ||
---|---|---|---|---|---|---|---|---|---|
datetime | |||||||||
2019-12-31 | distance | 16.38 | 32.68 | 54.240 | 1.425e+06 | 711.14 | 38.853 | 0.009 | 28.823 |
duration | 93.85 | 182.95 | 296.633 | 1.425e+06 | 8239.20 | 213.365 | 0.017 | 159.943 |
distance | duration | |
---|---|---|
datetime | ||
2019-12-31 | 5.537e+07 | 3.040e+08 |
2020
25% | 50% | 75% | count | max | mean | min | std | ||
---|---|---|---|---|---|---|---|---|---|
datetime | |||||||||
2020-12-31 | distance | 15.84 | 31.560 | 53.879 | 1.332e+06 | 624.57 | 38.491 | 0.010 | 29.453 |
duration | 91.00 | 177.852 | 296.000 | 1.332e+06 | 6913.00 | 213.047 | 0.033 | 162.972 |
distance | duration | |
---|---|---|
datetime | ||
2020-12-31 | 5.126e+07 | 2.837e+08 |
for year in years:
y = dfs[year, freq][['duration', 'distance']].groupby(dfs[year, freq].index).agg('sum')
y['pace'] = y['duration'] / y['distance']
y['nathletes'] = nathletes[year, freq]
y.loc[:, ['duration', 'distance']] = y.loc[:, ['duration', 'distance']
].div(y['nathletes'], axis=0)
offset = 30 if freq == 'm' else 0
y.index = dfs['2019', freq].index.dayofyear.unique() - offset
y.index.rename('Period', inplace=True)
last = y.iloc[-1]
last.name = 366
y = pd.concat([y, last.to_frame().transpose()]) # for plotting with steps
y = y[['nathletes', 'duration', 'distance', 'pace']]
y.rename(columns={'nathletes': 'N athletes', 'distance': 'Distance (km)',
'duration': 'Duration (min)', 'pace': 'Pace (min/km)'}, inplace=True)
if year == '2019':
data = y.copy(deep=True)
else:
data = pd.concat([data, y], axis=1, keys=years, names=['year', 'var'])
display_df(data, subset=data.columns)
year | 2019 | 2020 | ||||||
---|---|---|---|---|---|---|---|---|
var | N athletes | Duration (min) | Distance (km) | Pace (min/km) | N athletes | Duration (min) | Distance (km) | Pace (min/km) |
1 | 27314.000000 | 210.276115 | 38.593141 | 5.448536 | 27436.000000 | 206.787702 | 37.828180 | 5.466499 |
8 | 27312.000000 | 216.299579 | 39.905683 | 5.420270 | 27241.000000 | 210.645834 | 38.702974 | 5.442627 |
15 | 27061.000000 | 218.450586 | 40.276625 | 5.423756 | 26881.000000 | 214.586022 | 39.463562 | 5.437574 |
22 | 26878.000000 | 220.019951 | 40.716068 | 5.403762 | 26737.000000 | 215.768850 | 39.903718 | 5.407237 |
29 | 26919.000000 | 217.570147 | 40.238250 | 5.407048 | 27040.000000 | 217.188595 | 40.111466 | 5.414626 |
36 | 27244.000000 | 224.068211 | 41.610395 | 5.384910 | 26567.000000 | 218.135680 | 40.310068 | 5.411444 |
43 | 27329.000000 | 225.385986 | 41.879271 | 5.381803 | 26500.000000 | 220.851903 | 40.840300 | 5.407695 |
50 | 27400.000000 | 225.701242 | 41.920535 | 5.384026 | 26706.000000 | 219.898322 | 40.674300 | 5.406321 |
57 | 27557.000000 | 231.781647 | 43.028153 | 5.386744 | 26717.000000 | 218.658060 | 40.493002 | 5.399898 |
64 | 27306.000000 | 225.821350 | 42.098275 | 5.364147 | 26829.000000 | 219.459910 | 40.566601 | 5.409867 |
71 | 27838.000000 | 228.737126 | 42.577667 | 5.372233 | 26101.000000 | 201.484114 | 37.117060 | 5.428343 |
78 | 28065.000000 | 234.722391 | 43.728630 | 5.367705 | 25944.000000 | 204.896699 | 37.605107 | 5.448640 |
85 | 28114.000000 | 225.639340 | 42.100280 | 5.359569 | 25997.000000 | 208.159050 | 38.461806 | 5.412098 |
92 | 28469.000000 | 217.950097 | 40.290778 | 5.409429 | 26365.000000 | 213.870778 | 39.405905 | 5.427379 |
99 | 28172.000000 | 225.724543 | 41.741199 | 5.407716 | 26407.000000 | 213.753030 | 39.300959 | 5.438876 |
106 | 26890.000000 | 183.456972 | 33.046381 | 5.551500 | 26806.000000 | 218.728382 | 40.196011 | 5.441545 |
113 | 28012.000000 | 207.293646 | 37.585703 | 5.515226 | 26838.000000 | 216.700558 | 39.717423 | 5.456058 |
120 | 27151.000000 | 193.509774 | 34.869715 | 5.549508 | 27621.000000 | 219.927357 | 40.132779 | 5.479993 |
127 | 27391.000000 | 191.071371 | 34.522822 | 5.534639 | 27460.000000 | 219.358430 | 40.027285 | 5.480223 |
134 | 27856.000000 | 197.351224 | 35.679052 | 5.531291 | 27530.000000 | 223.425514 | 40.510039 | 5.515312 |
141 | 27493.000000 | 198.812015 | 35.688441 | 5.570768 | 27411.000000 | 224.502006 | 40.390854 | 5.558239 |
148 | 27415.000000 | 195.991812 | 35.254709 | 5.559309 | 27401.000000 | 222.894611 | 39.989451 | 5.573835 |
155 | 27789.000000 | 202.641443 | 36.166518 | 5.603012 | 27352.000000 | 218.700749 | 39.455818 | 5.542928 |
162 | 27679.000000 | 201.539423 | 36.091652 | 5.584101 | 27055.000000 | 222.922595 | 40.035212 | 5.568163 |
169 | 27792.000000 | 206.477589 | 36.746689 | 5.618944 | 26760.000000 | 221.195993 | 39.401501 | 5.613898 |
176 | 27504.000000 | 207.882402 | 36.725958 | 5.660367 | 26350.000000 | 219.507854 | 38.989154 | 5.629972 |
183 | 27904.000000 | 211.468754 | 37.577093 | 5.627597 | 25496.000000 | 217.396412 | 38.547042 | 5.639769 |
190 | 28089.000000 | 218.818075 | 38.850460 | 5.632316 | 25415.000000 | 218.545676 | 38.663187 | 5.652552 |
197 | 27907.000000 | 218.221118 | 38.703872 | 5.638225 | 25171.000000 | 218.048859 | 38.408135 | 5.677153 |
204 | 27990.000000 | 226.458517 | 40.194947 | 5.634005 | 24835.000000 | 216.702892 | 37.946145 | 5.710801 |
211 | 28281.000000 | 229.505495 | 40.847934 | 5.618534 | 24827.000000 | 216.620997 | 37.954358 | 5.707408 |
218 | 28435.000000 | 232.107293 | 41.614189 | 5.577600 | 24641.000000 | 215.529287 | 37.572860 | 5.736302 |
225 | 28651.000000 | 237.796260 | 42.483524 | 5.597376 | 24655.000000 | 216.264309 | 37.919923 | 5.703184 |
232 | 28784.000000 | 237.592378 | 42.762870 | 5.556044 | 24498.000000 | 214.267322 | 37.757502 | 5.674828 |
239 | 28787.000000 | 241.009973 | 43.329373 | 5.562277 | 24722.000000 | 212.524666 | 37.718943 | 5.634428 |
246 | 28994.000000 | 240.463802 | 43.650802 | 5.508806 | 24687.000000 | 212.478203 | 37.642970 | 5.644565 |
253 | 28857.000000 | 238.198908 | 43.297261 | 5.501478 | 24492.000000 | 209.069044 | 37.125616 | 5.631396 |
260 | 28687.000000 | 228.731593 | 41.624292 | 5.495147 | 24570.000000 | 208.130852 | 37.017860 | 5.622444 |
267 | 28857.000000 | 241.726969 | 44.021611 | 5.491098 | 24467.000000 | 205.255688 | 36.725060 | 5.588982 |
274 | 26878.000000 | 207.721578 | 37.943844 | 5.474447 | 24481.000000 | 213.590273 | 37.895543 | 5.636290 |
281 | 27926.000000 | 220.645628 | 40.293526 | 5.475957 | 24275.000000 | 205.655970 | 36.653498 | 5.610814 |
288 | 26817.000000 | 198.837001 | 36.392219 | 5.463723 | 24333.000000 | 204.783937 | 36.741124 | 5.573698 |
295 | 26954.000000 | 196.600499 | 35.824336 | 5.487903 | 24223.000000 | 204.121974 | 36.581772 | 5.579882 |
302 | 27159.000000 | 211.779905 | 38.351269 | 5.522110 | 24016.000000 | 202.318385 | 36.374829 | 5.562044 |
309 | 25471.000000 | 185.549201 | 34.086587 | 5.443467 | 24460.000000 | 202.991221 | 36.533016 | 5.556377 |
316 | 25655.000000 | 186.576752 | 34.164801 | 5.461081 | 24131.000000 | 203.075110 | 36.730022 | 5.528859 |
323 | 25867.000000 | 185.832674 | 34.320894 | 5.414564 | 24132.000000 | 204.215980 | 37.005085 | 5.518592 |
330 | 25845.000000 | 184.160858 | 33.741095 | 5.458058 | 24199.000000 | 204.329730 | 36.951906 | 5.529613 |
337 | 25253.000000 | 186.093574 | 34.248620 | 5.433608 | 23561.000000 | 202.804750 | 36.829727 | 5.506550 |
344 | 24416.000000 | 183.535501 | 33.813643 | 5.427854 | 23256.000000 | 202.651526 | 36.782441 | 5.509464 |
351 | 24274.000000 | 187.001214 | 34.534528 | 5.414906 | 22619.000000 | 202.151415 | 36.625871 | 5.519361 |
358 | 26334.000000 | 195.806977 | 35.813390 | 5.467424 | 23627.000000 | 198.716531 | 35.686390 | 5.568412 |
366 | 26334.000000 | 195.806977 | 35.813390 | 5.467424 | 23627.000000 | 198.716531 | 35.686390 | 5.568412 |
fig, axs = plt.subplots(4, 1, sharex=True, figsize=(12, 8))
cols = data['2019'].columns
precision = [0, 1, 1, 2]
for a, ax in enumerate(axs):
for y, year in enumerate(years):
ax.plot(np.linspace(0, 365, data[year].shape[0]), data[year][cols[a]],
color=colors[y], lw=3, label=year, drawstyle='steps-post')
msd = '{:g}±{:g}'.format(np.round(data[year][cols[a]].iloc[:-1].mean(), precision[a]),
np.round(data[year][cols[a]].iloc[:-1].std(), precision[a]))
ax.text(.98, .85-y/7, msd, ha='right', c=colors[y],
fontsize=14, transform=ax.transAxes)
ax.margins(x=0, y=0.3)
ax.tick_params(axis='both', which='major', labelsize=13)
ax.set_ylabel(cols[a])
axs[0].text(.97, 1.03, 'Mean±SD', ha='right', c='k',
fontsize=14, transform=axs[0].transAxes)
axs[0].set_xlim([0, 365])
axs[0].legend(['2019', '2020'], loc='lower left', frameon=True, framealpha=.5, fontsize=14)
axs[3].set_xlabel('Month')
x = nathletes['2019', 'm'].index.day_of_year.values
axs[3].set_xticks(np.append([0], x[:-1]))
axs[3].set_xticklabels(months, rotation=0, ha='center')
offset = matplotlib.transforms.ScaledTranslation(34/72, 0, fig.dpi_scale_trans)
for label in axs[3].get_xticklabels():
label.set_transform(label.get_transform() + offset)
plt.suptitle('Number of athletes and running volume per athlete at each {} (from only actual runs)'
.format(freq_s), fontsize=18)
fig.align_ylabels(axs)
plt.tight_layout(h_pad=.05)
plt.show()
The difference between 2020 and 2019 in the average running volume per period (day, week or month) will be normalized by the 2019 average running volume per period (a single number) because the year average running volume per period will also be shown in the plots and it will be easier to understand the data.
The difference between 2020 and 2019 in the number of athletes per period (day, week or month) can be normalized by the total number of athletes in 2019 or by the average number of athletes per period in 2019. We will adopt the second option because it seems more reasonable to compare the differences in weekly running volume with the differences in the number of athletes who actually ran on that week. Also, when calculating this relative difference, the numbers in the numerator and denominator will be equivalent.
However, because we show in the plots the total number of athletes in each year (after all, the mean values are based on the data of all athletes), it will not be possible to directly relate the plotted relative difference in the number of athletes with the total number of athletes in that year.
Be aware.
nathletesd = dict()
for frq in freqs:
# 2019 total number of athletes
Na = nruns['2019', 'd'].size
# 2019 average number of athletes per period (day, week or month)
#Na = estimate(nathletes['2019', frq])
# 2019 average running volume per period (day, week or month)
Vr = estimate(dfs['2019', frq][variables].values, axis=0)
dfs['2020', frq][vars_d] = (100 * (dfs['2020', frq][variables].values -
dfs['2019', frq][variables].values) / Vr)
nathletesd[frq] = pd.Series(100 * ((nathletes['2020', frq].values -
nathletes['2019', frq].values
) / estimate(nathletes['2019', frq])),
index=nathletes['2020', frq].index)
display(dfs['2020', freq])
athlete | distance | duration | country | distance_d | duration_d | |
---|---|---|---|---|---|---|
datetime | ||||||
2020-01-01 | 0 | 0.000 | 0.000 | United States | 0.000 | 0.000 |
2020-01-01 | 1 | 70.330 | 394.200 | Germany | 222.493 | 226.676 |
2020-01-01 | 2 | 14.650 | 79.067 | United Kingdom | 18.296 | -11.790 |
2020-01-01 | 3 | 41.410 | 195.667 | United Kingdom | -211.070 | -160.500 |
2020-01-01 | 4 | 41.340 | 209.100 | United States | 22.810 | 14.603 |
... | ... | ... | ... | ... | ... | ... |
2020-12-23 | 37594 | 128.154 | 572.587 | United Kingdom | 394.369 | 317.038 |
2020-12-23 | 37595 | 20.051 | 87.461 | United States | -450.299 | -334.071 |
2020-12-23 | 37596 | 144.636 | 625.774 | United States | 372.299 | 294.362 |
2020-12-23 | 37597 | 0.000 | 0.000 | United States | -109.220 | -109.896 |
2020-12-23 | 37598 | 102.052 | 847.220 | China | 191.423 | 326.483 |
1893424 rows × 6 columns
print('Relative difference in total number of athletes between years')
100 * (nruns['2020', 'd'].size - nruns['2019', 'd'].size) / nruns['2019', 'd'].size
Relative difference in total number of athletes between years
-3.6498956388003956
print('Relative difference in number of athletes per {} between years'.format(freq_s))
display(nathletesd[freq].describe().to_frame().T)
display_df(nathletesd[freq].groupby('datetime').agg(['mean']))
Relative difference in number of athletes per week between years
count | mean | std | min | 25% | 50% | 75% | max | |
---|---|---|---|---|---|---|---|---|
0 | 52.0 | -6.539 | 5.291 | -16.019 | -9.97 | -6.107 | -2.143 | 1.715 |
mean | |
---|---|
datetime | |
2020-01-01 | 0.445186 |
2020-01-08 | -0.259084 |
2020-01-15 | -0.656832 |
2020-01-22 | -0.514518 |
2020-01-29 | 0.441537 |
2020-02-05 | -2.470418 |
2020-02-12 | -3.025076 |
2020-02-19 | -2.532452 |
2020-02-26 | -3.065216 |
2020-03-04 | -1.740605 |
2020-03-11 | -6.338428 |
2020-03-18 | -7.739670 |
2020-03-25 | -7.725074 |
2020-04-01 | -7.677636 |
2020-04-08 | -6.440602 |
2020-04-15 | -0.306522 |
2020-04-22 | -4.284004 |
2020-04-29 | 1.715061 |
2020-05-06 | 0.251786 |
2020-05-13 | -1.189596 |
2020-05-20 | -0.299223 |
2020-05-27 | -0.051087 |
2020-06-03 | -1.594642 |
2020-06-10 | -2.277017 |
2020-06-17 | -3.765837 |
2020-06-24 | -4.211023 |
2020-07-01 | -8.786952 |
2020-07-08 | -9.757604 |
2020-07-15 | -9.983846 |
2020-07-22 | -11.512805 |
2020-07-29 | -12.603876 |
2020-08-05 | -13.844558 |
2020-08-12 | -14.581670 |
2020-08-19 | -15.639899 |
2020-08-26 | -14.833455 |
2020-09-02 | -15.716529 |
2020-09-09 | -15.928175 |
2020-09-16 | -15.023207 |
2020-09-23 | -16.019402 |
2020-09-30 | -8.746812 |
2020-10-07 | -13.322742 |
2020-10-14 | -9.064281 |
2020-10-21 | -9.965601 |
2020-10-28 | -11.469016 |
2020-11-04 | -3.689206 |
2020-11-11 | -5.561177 |
2020-11-18 | -6.331130 |
2020-11-25 | -6.006363 |
2020-12-02 | -6.174220 |
2020-12-09 | -4.232917 |
2020-12-16 | -6.039205 |
2020-12-23 | -9.878023 |
grouper = pd.Grouper(axis=0, freq='y', sort=True)
display(dfs['2020', freq][vars_d].groupby(grouper).describe().stack(level=0))
25% | 50% | 75% | count | max | mean | min | std | ||
---|---|---|---|---|---|---|---|---|---|
datetime | |||||||||
2020-12-31 | distance_d | -55.196 | 0.0 | 40.388 | 1.893e+06 | 1848.542 | -7.411 | -2385.349 | 100.692 |
duration_d | -56.036 | 0.0 | 42.803 | 1.893e+06 | 3933.133 | -6.678 | -4732.122 | 107.428 |
We will adopt the following rules of thumb for the magnitude of Cohen's d (https://doi.org/10.22237%2Fjmasm%2F1257035100):
effect_sizes = pd.DataFrame({'d': [.01, .2, .5, .8, 1.2, 2], 'effect size':
['Very small', 'Small', 'Medium', 'Large', 'Very large', 'Huge']})
effect_sizes
d | effect size | |
---|---|---|
0 | 0.01 | Very small |
1 | 0.20 | Small |
2 | 0.50 | Medium |
3 | 0.80 | Large |
4 | 1.20 | Very large |
5 | 2.00 | Huge |
n_periods = dfs['2020', freq].index.unique().size
alphaB = alpha / n_periods
alphaS = 1-(1-alpha)**(1/n_periods)
print('Number of comparisons: {}'.format(n_periods))
print('Alpha level: {:.2f}'.format(alpha))
print('Alpha level with Bonferroni correction: {:.5f}'.format(alphaB))
print('Alpha level with Sidak correction: {:.5f}'.format(alphaS))
Number of comparisons: 52 Alpha level: 0.05 Alpha level with Bonferroni correction: 0.00096 Alpha level with Sidak correction: 0.00099
from bootstrap_stat import bootstrap_stat as bp
data = pd.DataFrame([])
frq = 'd'
for year in years:
y = dfs[year, frq][['athlete', 'distance', 'duration']].groupby('athlete').sum() * 7 /365
y['pace'] = y['duration'] / y['distance']
for col in y.columns:
y.rename(columns={col: col+year}, inplace=True)
data = pd.concat([data, y], axis=1)
data = pd.concat([data, nruns[year, 'd'].to_frame(name='nruns'+year) * 7 / 365], axis=1)
# replace nans with zeros; merging 2019 and 2020 creates nans in nruns2020 due to nonexistent data
data['nruns2020'] = data['nruns2020'].fillna(0)
# replace nans with zeros; merging 2019 and 2020 creates nans in pace2020 due to no runs,
# not replacing nans will use only actual runs to compute pace (makes sense), but it will
# result in 2029 and 2020 having different number of athletes when computing averages.
#data['pace2020'] = data['pace2020'].fillna(0)
# relative differences
# normalize by global values
Vr = estimate(data[['distance2019', 'duration2019', 'pace2019', 'nruns2019']].values, axis=0)
# normalize by individual values
#Vr = data[['distance2019', 'duration2019', 'pace2019', 'nruns2019']].values
data[['distanced','durationd','paced','nrunsd']] = (100*(data[['distance2020','duration2020',
'pace2020','nruns2020']].values -
data[['distance2019','duration2019',
'pace2019','nruns2019']].values) / Vr)
display(data)
stat = ['count', 'mean', 'std', cohensd]
ys = data.agg(stat, axis=0).T
for var in tqdm(data.columns):
ys.loc[var, ['ci_inf', 'ci_sup', 'pvalue']] = ci_asl(data[var],
alpha2=alpha/2, boot=10000)
if var[-1] != 'd':
ys.loc[var, ['cohensd', 'pvalue']] = ['-', '-']
display(ys)
distance2019 | duration2019 | pace2019 | nruns2019 | distance2020 | duration2020 | pace2020 | nruns2020 | distanced | durationd | paced | nrunsd | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
athlete | ||||||||||||
0 | 11.636 | 71.388 | 6.135 | 1.055 | 5.185 | 30.184 | 5.821 | 0.940 | -22.068 | -25.668 | -5.370 | -4.671 |
1 | 53.140 | 306.499 | 5.768 | 4.353 | 40.601 | 235.223 | 5.794 | 3.203 | -42.897 | -44.400 | 0.442 | -46.708 |
2 | 19.859 | 124.023 | 6.245 | 1.822 | 9.432 | 64.498 | 6.838 | 1.247 | -35.670 | -37.080 | 10.142 | -23.354 |
3 | 29.050 | 138.089 | 4.754 | 2.992 | 71.588 | 312.317 | 4.363 | 4.756 | 145.516 | 108.533 | -6.683 | 71.619 |
4 | 22.380 | 113.521 | 5.073 | 2.225 | 30.759 | 151.684 | 4.931 | 3.663 | 28.665 | 23.773 | -2.414 | 58.385 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
37594 | 129.132 | 585.479 | 4.534 | 6.578 | 76.483 | 350.823 | 4.587 | 4.277 | -180.106 | -146.175 | 0.906 | -93.416 |
37595 | 118.046 | 492.265 | 4.170 | 6.444 | 115.919 | 486.186 | 4.194 | 6.348 | -7.276 | -3.787 | 0.412 | -3.892 |
37596 | 87.583 | 369.119 | 4.214 | 5.063 | 96.753 | 421.385 | 4.355 | 5.236 | 31.370 | 32.559 | 2.407 | 7.006 |
37597 | 41.694 | 219.792 | 5.272 | 3.107 | 40.746 | 229.677 | 5.637 | 3.126 | -3.244 | 6.158 | 6.247 | 0.778 |
37598 | 79.607 | 588.323 | 7.390 | 3.682 | 94.075 | 659.680 | 7.012 | 4.967 | 49.496 | 44.451 | -6.466 | 52.157 |
36412 rows × 12 columns
0%| | 0/12 [00:00<?, ?it/s]
count | mean | std | cohensd | ci_inf | ci_sup | pvalue | |
---|---|---|---|---|---|---|---|
distance2019 | 36412.0 | 29.232 | 22.977 | - | 29.002 | 29.467 | - |
duration2019 | 36412.0 | 160.530 | 119.248 | - | 159.304 | 161.778 | - |
pace2019 | 36412.0 | 5.848 | 8.791 | - | 5.790 | 5.950 | - |
nruns2019 | 36412.0 | 2.464 | 1.563 | - | 2.447 | 2.480 | - |
distance2020 | 36412.0 | 27.044 | 24.567 | - | 26.794 | 27.303 | - |
duration2020 | 36412.0 | 149.699 | 130.758 | - | 148.339 | 151.037 | - |
pace2020 | 35083.0 | 5.947 | 11.550 | - | 5.865 | 6.086 | - |
nruns2020 | 36412.0 | 2.410 | 1.713 | - | 2.392 | 2.428 | - |
distanced | 36412.0 | -7.485 | 47.941 | 0.156 | -7.985 | -6.985 | 0.0 |
durationd | 36412.0 | -6.747 | 48.547 | 0.139 | -7.238 | -6.245 | 0.0 |
paced | 35083.0 | 3.025 | 196.534 | 0.015 | 1.659 | 5.501 | 0.0 |
nrunsd | 36412.0 | -2.172 | 42.345 | 0.051 | -2.608 | -1.755 | 0.0 |
data = pd.DataFrame([])
frq = 'd'
for year in years:
y = dfs[year, frq][['athlete', 'distance', 'duration']].groupby('athlete').sum() * 7 /365
y['pace'] = y['duration'] / y['distance']
for col in y.columns:
y.rename(columns={col: col+year}, inplace=True)
data = pd.concat([data, y], axis=1)
data = pd.concat([data, nruns[year, 'd'].to_frame(name='nruns'+year) * 7 / 365], axis=1)
# replace nans with zeros; merging 2019 and 2020 creates nans in nruns2020 due to nonexistent data
data['nruns2020'] = data['nruns2020'].fillna(0)
# replace nans with zeros; merging 2019 and 2020 creates nans in pace2020 due to no runs,
# not replacing nans will use only actual runs to compute pace (makes sense), but it will
# result in 2029 and 2020 having different number of athletes when computing averages.
data['pace2020'] = data['pace2020'].fillna(0)
# relative differences
# normalize by global values
Vr = estimate(data[['distance2019', 'duration2019', 'pace2019', 'nruns2019']].values, axis=0)
# normalize by individual values
#Vr = data[['distance2019', 'duration2019', 'pace2019', 'nruns2019']].values
data[['distanced','durationd','paced','nrunsd']] = (100*(data[['distance2020','duration2020',
'pace2020','nruns2020']].values -
data[['distance2019','duration2019',
'pace2019','nruns2019']].values) / Vr)
stat = ['count', 'mean', 'std', cohensd]
ys = data.agg(stat, axis=0).T
for var in tqdm(data.columns):
ys.loc[var, ['ci_inf', 'ci_sup', 'pvalue']] = ci_asl(data[var],
alpha2=alpha/2, boot=10000)
if var[-1] != 'd':
ys.loc[var, ['cohensd', 'pvalue']] = ['-', '-']
display(ys)
0%| | 0/12 [00:00<?, ?it/s]
count | mean | std | cohensd | ci_inf | ci_sup | pvalue | |
---|---|---|---|---|---|---|---|
distance2019 | 36412.0 | 29.232 | 22.977 | - | 28.996 | 29.471 | - |
duration2019 | 36412.0 | 160.530 | 119.248 | - | 159.312 | 161.729 | - |
pace2019 | 36412.0 | 5.848 | 8.791 | - | 5.790 | 5.952 | - |
nruns2019 | 36412.0 | 2.464 | 1.563 | - | 2.448 | 2.480 | - |
distance2020 | 36412.0 | 27.044 | 24.567 | - | 26.789 | 27.293 | - |
duration2020 | 36412.0 | 149.699 | 130.758 | - | 148.387 | 151.038 | - |
pace2020 | 36412.0 | 5.730 | 11.392 | - | 5.650 | 5.868 | - |
nruns2020 | 36412.0 | 2.410 | 1.713 | - | 2.392 | 2.428 | - |
distanced | 36412.0 | -7.485 | 47.941 | 0.156 | -7.982 | -6.989 | 0.0 |
durationd | 36412.0 | -6.747 | 48.547 | 0.139 | -7.257 | -6.274 | 0.0 |
paced | 36412.0 | -2.011 | 245.118 | 0.008 | -4.418 | 0.705 | 0.123 |
nrunsd | 36412.0 | -2.172 | 42.345 | 0.051 | -2.602 | -1.735 | 0.0 |
for year in years:
print('Year: {}'.format(year))
print(' Number of days:', dfs[year, 'd'].index.value_counts().size)
print(' Number of athletes with a least one session:', nruns[year, 'd'].size)
print(' Number of activities:', dfs[year, 'd'].shape[0])
print(' Number of actual running activities:', nathletes[year, 'd'].sum())
nathlete = nruns['2019', 'd'].size
nactivity = nathletes['2019', 'd'].sum() + nathletes['2020', 'd'].sum()
print('Total number of actual running activities in 2019 and 2020:', nactivity)
nd = 100 * (nruns['2020', 'd'].size - nruns['2019', 'd'].size) / nruns['2019', 'd'].size
print('Relative difference in number of athletes [%]: {}'.format(nd))
Year: 2019 Number of days: 365 Number of athletes with a least one session: 36412 Number of activities: 13290380 Number of actual running activities: 4677389 Year: 2020 Number of days: 365 Number of athletes with a least one session: 35083 Number of activities: 13290380 Number of actual running activities: 4575794 Total number of actual running activities in 2019 and 2020: 9253183 Relative difference in number of athletes [%]: -3.6498956388003956
nwd = 100 * (nathletes['2020', 'w'].values - nathletes['2019', 'w'].values
) / nathletes['2019', 'w'].mean()
data = pd.DataFrame(data=np.c_[nathletes['2019', 'w'].values, nathletes['2020', 'w'].values, nwd],
columns=['nathletesw2019', 'nathletesw2020', 'nathleteswd'])
#display(data)
stat = ['count', 'mean', 'std', cohensd]
ys = data.agg(stat, axis=0).T
for var in tqdm(data.columns):
ys.loc[var, ['ci_inf', 'ci_sup', 'pvalue']] = ci_asl(data[var],
alpha2=alpha/2, boot=1000)
if var[-1] != 'd':
ys.loc[var, ['cohensd', 'pvalue']] = ['-', '-']
display(ys)
0%| | 0/3 [00:00<?, ?it/s]
count | mean | std | cohensd | ci_inf | ci_sup | pvalue | |
---|---|---|---|---|---|---|---|
nathletesw2019 | 52.0 | 27404.269 | 1075.724 | - | 27102.346 | 27679.385 | - |
nathletesw2020 | 52.0 | 25612.327 | 1365.308 | - | 25238.135 | 25984.558 | - |
nathleteswd | 52.0 | -6.539 | 5.291 | 1.236 | -8.056 | -5.118 | 0.0 |
dfsdata = None
if load_results:
try:
fname = path2 / 'dfsdata_{}_{}.pkl'.format(freq, country[1])
with open(fname, 'rb') as file:
dfsdata, nruns, c19idx = pickle.loads(file.read())
print('{} loaded.\n'.format(fname))
except Exception as e:
print(e, '\nError in loading {}.\nRunning analysis...'.format(fname))
from bootstrap_stat import bootstrap_stat as bp
if dfsdata is None:
print('1/3')
dfsdiff = describe(dfs['2020', freq],
variable=['distance_d', 'duration_d'],
new_variable=['distance', 'duration'], show=False)
print('2/3')
dfs2019 = describe(dfs['2019', freq],
variable=['distance', 'duration'],
new_variable=['distance2019', 'duration2019'], show=False)
print('3/3')
dfs2020 = describe(dfs['2020', freq],
variable=['distance', 'duration'],
new_variable=['distance2020', 'duration2020'], show=False)
dfsdata = pd.concat([dfsdiff, dfs2019, dfs2020], axis=1)
# add nathletes data
for var in ['distance', 'duration']:
dfsdata[var, 'nathletes'] = nathletesd[freq].values
for year in ['2019', '2020']:
dfsdata[var+year, 'nathletes'] = nathletes[year, freq].values
dfsdata = dfsdata.sort_index(axis=1)
# save data
try:
fname = path2 / 'dfsdata_{}_{}.pkl'.format(freq, country[1])
with open(fname, 'wb') as file:
pickle.dump((dfsdata, nruns, c19idx), file)
except Exception as e:
print(e, '\nError in saving {}.'.format(fname))
# display statistics
title = 'Results for all athletes of country: {}'.format(country[0])
display_dfsd(dfsdata, title)
../data/dfsdata_w_all.pkl loaded.
distance | distance2019 | distance2020 | duration | duration2019 | duration2020 | |||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ci_inf | ci_sup | cohensd | count | mean | nathletes | pvalue | std | ci_inf | ci_sup | cohensd | count | mean | nathletes | pvalue | std | ci_inf | ci_sup | cohensd | count | mean | nathletes | pvalue | std | ci_inf | ci_sup | cohensd | count | mean | nathletes | pvalue | std | ci_inf | ci_sup | cohensd | count | mean | nathletes | pvalue | std | ci_inf | ci_sup | cohensd | count | mean | nathletes | pvalue | std | |
Period | ||||||||||||||||||||||||||||||||||||||||||||||||
1 | -2.499744 | -0.567121 | 0.016277 | 36412 | -1.528932 | 0.445186 | 0.0018 | 93.929190 | 28.644250 | 29.255393 | 0.972958 | 36412 | 28.950156 | 27314 | 0.0000 | 29.754780 | 28.193737 | 28.813708 | 0.949189 | 36412 | 28.503074 | 27436 | 0.0000 | 30.028860 | -2.186130 | -0.204216 | 0.012426 | 36412 | -1.198103 | 0.445186 | 0.0183 | 96.417481 | 156.109886 | 159.376670 | 0.994965 | 36412 | 157.735961 | 27314 | 0.0000 | 158.534112 | 154.167371 | 157.457889 | 0.970611 | 36412 | 155.812024 | 27436 | 0.0000 | 160.529847 |
8 | -4.331955 | -2.353826 | 0.034737 | 36412 | -3.343197 | -0.259084 | 0.0000 | 96.241992 | 29.622279 | 30.239576 | 0.992297 | 36412 | 29.932550 | 27312 | 0.0000 | 30.164917 | 28.643818 | 29.265536 | 0.955630 | 36412 | 28.954952 | 27241 | 0.0000 | 30.299343 | -3.904785 | -1.898761 | 0.029572 | 36412 | -2.896661 | -0.259084 | 0.0000 | 97.952391 | 160.613525 | 163.890187 | 1.018178 | 36412 | 162.242505 | 27312 | 0.0000 | 159.345895 | 155.948575 | 159.241663 | 0.977589 | 36412 | 157.590991 | 27241 | 0.0000 | 161.203729 |
15 | -3.728039 | -1.742269 | 0.028350 | 36412 | -2.733606 | -0.656832 | 0.0000 | 96.424707 | 29.619682 | 30.243141 | 0.985443 | 36412 | 29.933147 | 27061 | 0.0000 | 30.375310 | 28.821034 | 29.448687 | 0.953691 | 36412 | 29.133802 | 26881 | 0.0000 | 30.548476 | -3.470117 | -1.428693 | 0.024696 | 36412 | -2.449150 | -0.656832 | 0.0000 | 99.171336 | 160.700888 | 164.017164 | 1.003891 | 36412 | 162.350085 | 27061 | 0.0000 | 161.720777 | 156.746008 | 160.092655 | 0.972528 | 36412 | 158.417194 | 26881 | 0.0000 | 162.892099 |
22 | -3.588715 | -1.569640 | 0.026178 | 36412 | -2.579107 | -0.514518 | 0.0000 | 98.523332 | 29.738564 | 30.372772 | 0.969483 | 36412 | 30.055105 | 26878 | 0.0000 | 31.001166 | 28.982597 | 29.621966 | 0.941309 | 36412 | 29.300937 | 26737 | 0.0000 | 31.127851 | -3.491327 | -1.458150 | 0.025084 | 36412 | -2.474462 | -0.514518 | 0.0000 | 98.646505 | 160.729190 | 164.076744 | 1.002993 | 36412 | 162.410641 | 26878 | 0.0000 | 161.926047 | 156.761756 | 160.113193 | 0.970145 | 36412 | 158.437102 | 26737 | 0.0000 | 163.312884 |
29 | -0.874299 | 1.145236 | 0.001376 | 36412 | 0.135301 | 0.441537 | 0.7916 | 98.313694 | 29.431696 | 30.062534 | 0.962642 | 36412 | 29.747705 | 26919 | 0.0000 | 30.902135 | 29.465619 | 30.108135 | 0.949218 | 36412 | 29.787269 | 27040 | 0.0000 | 31.380864 | -0.761120 | 1.307605 | 0.002740 | 36412 | 0.273791 | 0.441537 | 0.6024 | 99.923351 | 159.156875 | 162.531188 | 0.982547 | 36412 | 160.847270 | 26919 | 0.0000 | 163.704359 | 159.568903 | 162.995333 | 0.973718 | 36412 | 161.286928 | 27040 | 0.0000 | 165.640251 |
36 | -6.922447 | -4.858545 | 0.058739 | 36412 | -5.890273 | -2.470418 | 0.0000 | 100.279514 | 30.807574 | 31.460183 | 0.984431 | 36412 | 31.133516 | 27244 | 0.0000 | 31.625894 | 29.088014 | 29.737129 | 0.931579 | 36412 | 29.411117 | 26567 | 0.0000 | 31.571258 | -6.323687 | -4.247158 | 0.052352 | 36412 | -5.289857 | -2.470418 | 0.0000 | 101.044520 | 165.959841 | 169.336932 | 1.018157 | 36412 | 167.651168 | 27244 | 0.0000 | 164.661334 | 157.443120 | 160.869301 | 0.957459 | 36412 | 159.156613 | 26567 | 0.0000 | 166.228197 |
43 | -6.893589 | -4.801315 | 0.057492 | 36412 | -5.846568 | -3.025076 | 0.0000 | 101.694089 | 31.105195 | 31.758578 | 0.990883 | 36412 | 31.432456 | 27329 | 0.0000 | 31.721671 | 29.396786 | 30.049837 | 0.932206 | 36412 | 29.722837 | 26500 | 0.0000 | 31.884413 | -6.287340 | -4.197525 | 0.051585 | 36412 | -5.250427 | -3.025076 | 0.0000 | 101.782639 | 167.455950 | 170.868121 | 1.021110 | 36412 | 169.163287 | 27329 | 0.0000 | 165.666113 | 159.014675 | 162.448657 | 0.958495 | 36412 | 160.732051 | 26500 | 0.0000 | 167.692196 |
50 | -6.904102 | -4.800203 | 0.057279 | 36412 | -5.858228 | -2.532452 | 0.0000 | 102.275393 | 31.216513 | 31.874288 | 0.986753 | 36412 | 31.545168 | 27400 | 0.0000 | 31.968663 | 29.505562 | 30.158824 | 0.940062 | 36412 | 29.832139 | 26706 | 0.0000 | 31.734225 | -6.385927 | -4.262472 | 0.051588 | 36412 | -5.329291 | -2.532452 | 0.0000 | 103.304609 | 168.126954 | 171.562614 | 1.013012 | 36412 | 169.839999 | 27400 | 0.0000 | 167.658394 | 159.574571 | 162.990438 | 0.968381 | 36412 | 161.282121 | 26706 | 0.0000 | 166.548132 |
57 | -10.819771 | -8.701921 | 0.094341 | 36412 | -9.755942 | -3.065216 | 0.0000 | 103.411511 | 32.235797 | 32.892337 | 1.016414 | 36412 | 32.564177 | 27557 | 0.0000 | 32.038288 | 29.388582 | 30.034926 | 0.942419 | 36412 | 29.711401 | 26717 | 0.0000 | 31.526745 | -10.406049 | -8.251265 | 0.089009 | 36412 | -9.326309 | -3.065216 | 0.0000 | 104.779456 | 173.698072 | 177.154662 | 1.041282 | 36412 | 175.414887 | 27557 | 0.0000 | 168.460577 | 158.728080 | 162.156350 | 0.965753 | 36412 | 160.438520 | 26717 | 0.0000 | 166.127972 |
64 | -6.820829 | -4.670105 | 0.055071 | 36412 | -5.745462 | -1.740605 | 0.0000 | 104.327661 | 31.241140 | 31.904343 | 0.978447 | 36412 | 31.570238 | 27306 | 0.0000 | 32.265653 | 29.564482 | 30.217918 | 0.938217 | 36412 | 29.890183 | 26829 | 0.0000 | 31.858510 | -5.837797 | -3.689755 | 0.045467 | 36412 | -4.761120 | -1.740605 | 0.0000 | 104.716100 | 167.635200 | 171.084962 | 1.005241 | 36412 | 169.347407 | 27306 | 0.0000 | 168.464440 | 159.980371 | 163.424817 | 0.962783 | 36412 | 161.701909 | 26829 | 0.0000 | 167.952683 |
71 | -21.387353 | -19.274926 | 0.197877 | 36412 | -20.332194 | -6.338428 | 0.0000 | 102.751523 | 32.221860 | 32.884548 | 1.003911 | 36412 | 32.551826 | 27838 | 0.0000 | 32.424999 | 26.302746 | 26.910269 | 0.898268 | 36412 | 26.606404 | 26101 | 0.0000 | 29.619673 | -20.022895 | -17.900633 | 0.182960 | 36412 | -18.960605 | -6.338428 | 0.0000 | 103.632417 | 173.133746 | 176.643813 | 1.020944 | 36412 | 174.875978 | 27838 | 0.0000 | 171.288580 | 142.813773 | 146.049380 | 0.921809 | 36412 | 144.428674 | 26101 | 0.0000 | 156.679526 |
78 | -24.750265 | -22.525925 | 0.219415 | 36412 | -23.631821 | -7.739670 | 0.0000 | 107.703522 | 33.361162 | 34.051047 | 1.009903 | 36412 | 33.704383 | 28065 | 0.0000 | 33.373884 | 26.488512 | 27.098448 | 0.897913 | 36412 | 26.794103 | 25944 | 0.0000 | 29.840412 | -22.858004 | -20.645181 | 0.201946 | 36412 | -21.748251 | -7.739670 | 0.0000 | 107.693645 | 179.140913 | 182.704751 | 1.036725 | 36412 | 180.915190 | 28065 | 0.0000 | 174.506491 | 144.361255 | 147.628709 | 0.916318 | 36412 | 145.991430 | 25944 | 0.0000 | 159.323912 |
85 | -18.329787 | -16.176747 | 0.164198 | 36412 | -17.254536 | -7.725074 | 0.0000 | 105.083557 | 32.176665 | 32.837840 | 1.014848 | 36412 | 32.505967 | 28114 | 0.0000 | 32.030383 | 27.149489 | 27.772487 | 0.905548 | 36412 | 27.460496 | 25997 | 0.0000 | 30.324714 | -17.026211 | -14.861282 | 0.151522 | 36412 | -15.941444 | -7.725074 | 0.0000 | 105.209044 | 172.494784 | 175.931448 | 1.039723 | 36412 | 174.217962 | 28114 | 0.0000 | 167.561879 | 146.985235 | 150.265565 | 0.927021 | 36412 | 148.618884 | 25997 | 0.0000 | 160.318761 |
92 | -11.223472 | -9.075262 | 0.097216 | 36412 | -10.152865 | -7.677636 | 0.0000 | 104.435635 | 31.197214 | 31.808773 | 1.062549 | 36412 | 31.501652 | 28469 | 0.0000 | 29.647251 | 28.216584 | 28.850866 | 0.924588 | 36412 | 28.532810 | 26365 | 0.0000 | 30.860011 | -10.796075 | -8.583018 | 0.089787 | 36412 | -9.682019 | -7.677636 | 0.0000 | 107.832817 | 168.766663 | 172.061915 | 1.062365 | 36412 | 170.405946 | 28469 | 0.0000 | 160.402511 | 153.168115 | 156.536022 | 0.943252 | 36412 | 154.858373 | 26365 | 0.0000 | 164.174902 |
99 | -14.059822 | -11.891931 | 0.123555 | 36412 | -12.971508 | -6.440602 | 0.0000 | 104.985588 | 31.985813 | 32.606806 | 1.066305 | 36412 | 32.295207 | 28172 | 0.0000 | 30.287022 | 28.189186 | 28.817475 | 0.929986 | 36412 | 28.502154 | 26407 | 0.0000 | 30.647922 | -13.336068 | -11.108786 | 0.111917 | 36412 | -12.220322 | -6.440602 | 0.0000 | 109.190710 | 172.968940 | 176.337739 | 1.059910 | 36412 | 174.643300 | 28172 | 0.0000 | 164.771768 | 153.340541 | 156.703134 | 0.947812 | 36412 | 155.019671 | 26407 | 0.0000 | 163.555258 |
106 | 16.640475 | 18.833146 | 0.165357 | 36412 | 17.739292 | -0.306522 | 0.0000 | 107.278532 | 24.130378 | 24.679651 | 0.912643 | 36412 | 24.404514 | 26890 | 0.0000 | 26.740468 | 29.272668 | 29.914848 | 0.947075 | 36412 | 29.591735 | 26806 | 0.0000 | 31.245397 | 14.786960 | 17.026629 | 0.145221 | 36412 | 15.906579 | -0.306522 | 0.0000 | 109.533847 | 133.955702 | 137.017056 | 0.908485 | 36412 | 135.481653 | 26890 | 0.0000 | 149.129257 | 159.309855 | 162.750178 | 0.962498 | 36412 | 161.024745 | 26806 | 0.0000 | 167.298753 |
113 | 0.153575 | 2.298443 | 0.011795 | 36412 | 1.228984 | -4.284004 | 0.0247 | 104.194121 | 28.631216 | 29.201610 | 1.047129 | 36412 | 28.914938 | 28012 | 0.0000 | 27.613532 | 28.958322 | 29.593025 | 0.947831 | 36412 | 29.274310 | 26838 | 0.0000 | 30.885566 | -0.972052 | 1.282208 | 0.001418 | 36412 | 0.155632 | -4.284004 | 0.7866 | 109.779177 | 157.889010 | 161.083764 | 1.023555 | 36412 | 159.472416 | 28012 | 0.0000 | 155.802527 | 158.019061 | 161.420718 | 0.962051 | 36412 | 159.722332 | 26838 | 0.0000 | 166.022652 |
120 | 14.160955 | 16.222651 | 0.150504 | 36412 | 15.192448 | 1.715061 | 0.0000 | 100.944102 | 25.717558 | 26.285488 | 0.940815 | 36412 | 26.000978 | 27151 | 0.0000 | 27.636641 | 30.123810 | 30.760462 | 0.978334 | 36412 | 30.443466 | 27621 | 0.0000 | 31.117661 | 12.933499 | 15.130269 | 0.131307 | 36412 | 14.034793 | 1.715061 | 0.0000 | 106.885228 | 142.672594 | 145.922870 | 0.913650 | 36412 | 144.292647 | 27151 | 0.0000 | 157.929957 | 165.091709 | 168.584726 | 0.984164 | 36412 | 166.829988 | 27621 | 0.0000 | 169.514499 |
127 | 13.401994 | 15.435942 | 0.146177 | 36412 | 14.419938 | 0.251786 | 0.0000 | 98.646773 | 25.689404 | 26.251617 | 0.944934 | 36412 | 25.969862 | 27391 | 0.0000 | 27.483256 | 29.864049 | 30.508152 | 0.964411 | 36412 | 30.186456 | 27460 | 0.0000 | 31.300420 | 12.411781 | 14.606804 | 0.126210 | 36412 | 13.510037 | 0.251786 | 0.0000 | 107.043951 | 142.092281 | 145.400017 | 0.891934 | 36412 | 143.733822 | 27391 | 0.0000 | 161.148449 | 163.679957 | 167.190187 | 0.967549 | 36412 | 165.428499 | 27460 | 0.0000 | 170.976943 |
134 | 10.380892 | 12.413435 | 0.114984 | 36412 | 11.398637 | -1.189596 | 0.0000 | 99.132387 | 27.009977 | 27.582546 | 0.976882 | 36412 | 27.295278 | 27856 | 0.0000 | 27.941221 | 30.303959 | 30.953211 | 0.969607 | 36412 | 30.628402 | 27530 | 0.0000 | 31.588481 | 10.024156 | 12.319845 | 0.100172 | 36412 | 11.176270 | -1.189596 | 0.0000 | 111.571055 | 149.273169 | 152.707611 | 0.904523 | 36412 | 150.978131 | 27856 | 0.0000 | 166.914704 | 167.138262 | 170.726291 | 0.967733 | 36412 | 168.925200 | 27530 | 0.0000 | 174.557609 |
141 | 10.788892 | 12.869439 | 0.117525 | 36412 | 11.831203 | -0.299223 | 0.0000 | 100.669778 | 26.653482 | 27.241182 | 0.943167 | 36412 | 26.946675 | 27493 | 0.0000 | 28.570408 | 30.075289 | 30.736771 | 0.947808 | 36412 | 30.406286 | 27411 | 0.0000 | 32.080622 | 10.615698 | 12.916312 | 0.105685 | 36412 | 11.764545 | -0.299223 | 0.0000 | 111.317372 | 148.411105 | 151.844645 | 0.899558 | 36412 | 150.113664 | 27493 | 0.0000 | 166.874994 | 167.157585 | 170.868318 | 0.938087 | 36412 | 169.005397 | 27411 | 0.0000 | 180.159670 |
148 | 11.130524 | 13.152248 | 0.123021 | 36412 | 12.138481 | -0.051087 | 0.0000 | 98.670143 | 26.257452 | 26.831934 | 0.947559 | 36412 | 26.543663 | 27415 | 0.0000 | 28.012679 | 29.771282 | 30.418661 | 0.954364 | 36412 | 30.093127 | 27401 | 0.0000 | 31.532130 | 11.464559 | 13.665556 | 0.117056 | 36412 | 12.560390 | -0.051087 | 0.0000 | 107.302228 | 145.916647 | 149.217837 | 0.918953 | 36412 | 147.564416 | 27415 | 0.0000 | 160.578783 | 165.930898 | 169.567448 | 0.948767 | 36412 | 167.734133 | 27401 | 0.0000 | 176.791641 |
155 | 5.951045 | 7.979176 | 0.070325 | 36412 | 6.965481 | -1.594642 | 0.0000 | 99.046748 | 27.304799 | 27.899833 | 0.954486 | 36412 | 27.601653 | 27789 | 0.0000 | 28.917832 | 29.323136 | 29.958001 | 0.960414 | 36412 | 29.638458 | 27352 | 0.0000 | 30.860092 | 4.874114 | 7.108875 | 0.055144 | 36412 | 5.997833 | -1.594642 | 0.0000 | 108.766352 | 152.929810 | 156.379218 | 0.919648 | 36412 | 154.652396 | 27789 | 0.0000 | 168.164781 | 162.522595 | 166.036767 | 0.961313 | 36412 | 164.283832 | 27352 | 0.0000 | 170.895200 |
162 | 6.895639 | 8.903893 | 0.080699 | 36412 | 7.905399 | -2.277017 | 0.0000 | 97.962125 | 27.144298 | 27.725960 | 0.970062 | 36412 | 27.435484 | 27679 | 0.0000 | 28.282190 | 29.428371 | 30.068165 | 0.952893 | 36412 | 29.747135 | 27055 | 0.0000 | 31.217720 | 6.636662 | 8.860833 | 0.071741 | 36412 | 7.743333 | -2.277017 | 0.0000 | 107.935048 | 151.532853 | 154.882975 | 0.935546 | 36412 | 153.202507 | 27679 | 0.0000 | 163.757345 | 163.851347 | 167.445660 | 0.948830 | 36412 | 165.636900 | 27055 | 0.0000 | 174.569540 |
169 | 2.107075 | 4.116660 | 0.031842 | 36412 | 3.110641 | -3.765837 | 0.0000 | 97.689599 | 27.749904 | 28.343275 | 0.970862 | 36412 | 28.047456 | 27792 | 0.0000 | 28.889243 | 28.637600 | 29.276301 | 0.934130 | 36412 | 28.957052 | 26760 | 0.0000 | 30.998958 | 1.958707 | 4.230257 | 0.027925 | 36412 | 3.091777 | -3.765837 | 0.0000 | 110.716729 | 155.846790 | 159.355487 | 0.924293 | 36412 | 157.597088 | 27792 | 0.0000 | 170.505480 | 160.744399 | 164.369075 | 0.920558 | 36412 | 162.561924 | 26760 | 0.0000 | 176.590545 |
176 | 0.598123 | 2.637927 | 0.016356 | 36412 | 1.620440 | -4.211023 | 0.0019 | 99.076062 | 27.442069 | 28.038997 | 0.948323 | 36412 | 27.741150 | 27504 | 0.0000 | 29.252864 | 27.898168 | 28.535160 | 0.911468 | 36412 | 28.214990 | 26350 | 0.0000 | 30.955555 | -0.008905 | 2.282758 | 0.010212 | 36412 | 1.136192 | -4.211023 | 0.0516 | 111.262368 | 155.271358 | 158.799372 | 0.908980 | 36412 | 157.025090 | 27504 | 0.0000 | 172.748632 | 157.055550 | 160.669493 | 0.904047 | 36412 | 158.849609 | 26350 | 0.0000 | 175.709530 |
183 | -7.192073 | -5.156709 | 0.062362 | 36412 | -6.175773 | -8.786952 | 0.0000 | 99.030970 | 28.495324 | 29.095577 | 0.985892 | 36412 | 28.796858 | 27904 | 0.0000 | 29.208937 | 26.675677 | 27.302469 | 0.884220 | 36412 | 26.990975 | 25496 | 0.0000 | 30.525195 | -7.243808 | -4.999232 | 0.055736 | 36412 | -6.124141 | -8.786952 | 0.0000 | 109.876960 | 160.330956 | 163.783554 | 0.962110 | 36412 | 162.057127 | 27904 | 0.0000 | 168.439245 | 150.436466 | 154.029844 | 0.873134 | 36412 | 152.222864 | 25496 | 0.0000 | 174.340721 |
190 | -11.246202 | -9.174910 | 0.101087 | 36412 | -10.203976 | -9.757604 | 0.0000 | 100.942229 | 29.660772 | 30.277200 | 0.994340 | 36412 | 29.970080 | 28089 | 0.0000 | 30.140680 | 26.673066 | 27.304018 | 0.875644 | 36412 | 26.986293 | 25415 | 0.0000 | 30.818804 | -11.303717 | -8.946595 | 0.088436 | 36412 | -10.125389 | -9.757604 | 0.0000 | 114.493721 | 167.006728 | 170.614476 | 0.959621 | 36412 | 168.800969 | 28089 | 0.0000 | 175.903764 | 150.711212 | 154.381485 | 0.854914 | 36412 | 152.541425 | 25415 | 0.0000 | 178.428919 |
197 | -11.680775 | -9.619508 | 0.106022 | 36412 | -10.644657 | -9.983846 | 0.0000 | 100.400835 | 29.356006 | 29.972771 | 0.985163 | 36412 | 29.663543 | 27907 | 0.0000 | 30.110290 | 26.236332 | 26.863960 | 0.869725 | 36412 | 26.550895 | 25171 | 0.0000 | 30.527931 | -11.449319 | -9.114450 | 0.090801 | 36412 | -10.285235 | -9.983846 | 0.0000 | 113.271832 | 165.445263 | 169.040697 | 0.953761 | 36412 | 167.249718 | 27907 | 0.0000 | 175.358163 | 148.926006 | 152.553126 | 0.855170 | 36412 | 150.733490 | 25171 | 0.0000 | 176.261492 |
204 | -18.217598 | -16.095870 | 0.166566 | 36412 | -17.155766 | -11.512805 | 0.0000 | 102.996954 | 30.580021 | 31.217826 | 0.999224 | 36412 | 30.897961 | 27990 | 0.0000 | 30.921943 | 25.569034 | 26.197959 | 0.848565 | 36412 | 25.881372 | 24835 | 0.0000 | 30.500150 | -17.568872 | -15.144299 | 0.138475 | 36412 | -16.362916 | -11.512805 | 0.0000 | 118.165382 | 172.225813 | 175.940226 | 0.966234 | 36412 | 174.079257 | 27990 | 0.0000 | 180.162567 | 145.954974 | 149.673989 | 0.817225 | 36412 | 147.803371 | 24835 | 0.0000 | 180.860156 |
211 | -21.058883 | -18.936489 | 0.193508 | 36412 | -19.998108 | -12.603876 | 0.0000 | 103.345218 | 31.404475 | 32.047119 | 1.009367 | 36412 | 31.726365 | 28281 | 0.0000 | 31.431943 | 25.568332 | 26.194604 | 0.851999 | 36412 | 25.878634 | 24827 | 0.0000 | 30.374032 | -20.252896 | -17.806743 | 0.159531 | 36412 | -19.028129 | -12.603876 | 0.0000 | 119.275763 | 176.390670 | 180.151723 | 0.977051 | 36412 | 178.255655 | 28281 | 0.0000 | 182.442490 | 145.860250 | 149.568638 | 0.818884 | 36412 | 147.699920 | 24827 | 0.0000 | 180.367285 |
218 | -25.248499 | -23.110950 | 0.233294 | 36412 | -24.181205 | -13.844558 | 0.0000 | 103.651213 | 32.172792 | 32.823318 | 1.022263 | 36412 | 32.497513 | 28435 | 0.0000 | 31.789774 | 25.116840 | 25.735513 | 0.841521 | 36412 | 25.426586 | 24641 | 0.0000 | 30.215020 | -23.273535 | -20.830475 | 0.186133 | 36412 | -22.047027 | -13.844558 | 0.0000 | 118.447877 | 179.399294 | 183.104909 | 1.012018 | 36412 | 181.258126 | 28435 | 0.0000 | 179.105673 | 143.998958 | 147.742756 | 0.799728 | 36412 | 145.854585 | 24641 | 0.0000 | 182.380241 |
225 | -27.589381 | -25.436639 | 0.253422 | 36412 | -26.511648 | -14.581670 | 0.0000 | 104.614550 | 33.099251 | 33.762118 | 1.035780 | 36412 | 33.428415 | 28651 | 0.0000 | 32.273667 | 25.366207 | 25.987452 | 0.845965 | 36412 | 25.676032 | 24655 | 0.0000 | 30.351178 | -26.537989 | -24.115291 | 0.214879 | 36412 | -25.330537 | -14.581670 | 0.0000 | 117.882979 | 185.228267 | 189.026199 | 1.010064 | 36412 | 187.111410 | 28651 | 0.0000 | 185.247020 | 144.614042 | 148.270042 | 0.820406 | 36412 | 146.435146 | 24655 | 0.0000 | 178.491077 |
232 | -29.803073 | -27.660336 | 0.275247 | 36412 | -28.730355 | -15.639899 | 0.0000 | 104.380362 | 33.472872 | 34.138409 | 1.051509 | 36412 | 33.804417 | 28784 | 0.0000 | 32.148479 | 25.094782 | 25.712030 | 0.842685 | 36412 | 25.403254 | 24498 | 0.0000 | 30.145622 | -28.380059 | -26.000928 | 0.234631 | 36412 | -27.188447 | -15.639899 | 0.0000 | 115.877377 | 185.982123 | 189.670077 | 1.049344 | 36412 | 187.818824 | 28784 | 0.0000 | 178.986835 | 142.349109 | 145.990570 | 0.815718 | 36412 | 144.159092 | 24498 | 0.0000 | 176.726657 |
239 | -30.637217 | -28.504341 | 0.284283 | 36412 | -29.569226 | -14.833455 | 0.0000 | 104.013362 | 33.923410 | 34.591369 | 1.056114 | 36412 | 34.255813 | 28787 | 0.0000 | 32.435726 | 25.304202 | 25.916497 | 0.860789 | 36412 | 25.609351 | 24722 | 0.0000 | 29.751011 | -29.965194 | -27.621412 | 0.252158 | 36412 | -28.799177 | -14.833455 | 0.0000 | 114.210915 | 188.665628 | 192.416896 | 1.040254 | 36412 | 190.540319 | 28787 | 0.0000 | 183.167032 | 142.555771 | 146.038960 | 0.853232 | 36412 | 144.294045 | 24722 | 0.0000 | 169.114639 |
246 | -32.670771 | -30.512819 | 0.301430 | 36412 | -31.587037 | -15.716529 | 0.0000 | 104.790557 | 34.428875 | 35.090664 | 1.081259 | 36412 | 34.758084 | 28994 | 0.0000 | 32.145946 | 25.215758 | 25.827989 | 0.862871 | 36412 | 25.521586 | 24687 | 0.0000 | 29.577521 | -30.691649 | -28.356450 | 0.260468 | 36412 | -29.528406 | -15.716529 | 0.0000 | 113.366702 | 189.660624 | 193.295404 | 1.081010 | 36412 | 191.475543 | 28994 | 0.0000 | 177.126579 | 142.323361 | 145.789757 | 0.854337 | 36412 | 144.058261 | 24687 | 0.0000 | 168.619955 |
253 | -33.010826 | -30.878171 | 0.306485 | 36412 | -31.946665 | -15.928175 | 0.0000 | 104.235528 | 33.984853 | 34.642435 | 1.073648 | 36412 | 34.313662 | 28857 | 0.0000 | 31.959879 | 24.673615 | 25.270876 | 0.861889 | 36412 | 24.972003 | 24492 | 0.0000 | 28.973579 | -31.141459 | -28.828484 | 0.266369 | 36412 | -29.983823 | -15.928175 | 0.0000 | 112.564937 | 186.967883 | 190.587981 | 1.069604 | 36412 | 188.775840 | 28857 | 0.0000 | 176.491353 | 138.951901 | 142.318210 | 0.855151 | 36412 | 140.627239 | 24492 | 0.0000 | 164.447204 |
260 | -27.775639 | -25.666557 | 0.260235 | 36412 | -26.724611 | -15.023207 | 0.0000 | 102.694170 | 32.475635 | 33.114557 | 1.051717 | 36412 | 32.793476 | 28687 | 0.0000 | 31.180900 | 24.680818 | 25.279715 | 0.857527 | 36412 | 24.978821 | 24570 | 0.0000 | 29.128912 | -25.920006 | -23.612547 | 0.219642 | 36412 | -24.761778 | -15.023207 | 0.0000 | 112.736764 | 178.421051 | 182.015191 | 1.034403 | 36412 | 180.204966 | 28687 | 0.0000 | 174.211529 | 138.726805 | 142.140670 | 0.845067 | 36412 | 140.442026 | 24570 | 0.0000 | 166.190323 |
267 | -35.972500 | -33.864739 | 0.342222 | 36412 | -34.917454 | -16.019402 | 0.0000 | 102.031517 | 34.571425 | 35.203031 | 1.132778 | 36412 | 34.887719 | 28857 | 0.0000 | 30.798361 | 24.379427 | 24.974841 | 0.852710 | 36412 | 24.677360 | 24467 | 0.0000 | 28.939924 | -34.546947 | -32.268648 | 0.301910 | 36412 | -33.410087 | -16.019402 | 0.0000 | 110.662231 | 189.822535 | 193.318162 | 1.124478 | 36412 | 191.571876 | 28857 | 0.0000 | 170.365117 | 136.246249 | 139.607832 | 0.844842 | 36412 | 137.921315 | 24467 | 0.0000 | 163.250971 |
274 | -9.688850 | -7.606354 | 0.085218 | 36412 | -8.653190 | -8.746812 | 0.0000 | 101.541544 | 27.705108 | 28.314987 | 0.939042 | 36412 | 28.008751 | 26878 | 0.0000 | 29.826952 | 25.179002 | 25.782228 | 0.869080 | 36412 | 25.478435 | 24481 | 0.0000 | 29.316558 | -7.194488 | -4.927354 | 0.054817 | 36412 | -6.058329 | -8.746812 | 0.0000 | 110.518278 | 151.644852 | 155.020383 | 0.931371 | 36412 | 153.332433 | 26878 | 0.0000 | 164.630856 | 141.901836 | 145.322761 | 0.855912 | 36412 | 143.603853 | 24481 | 0.0000 | 167.778833 |
281 | -23.166826 | -21.070572 | 0.216574 | 36412 | -22.115603 | -13.322742 | 0.0000 | 102.115855 | 30.594580 | 31.209831 | 1.029944 | 36412 | 30.902917 | 27926 | 0.0000 | 30.004467 | 24.138651 | 24.734248 | 0.839410 | 36412 | 24.436001 | 24275 | 0.0000 | 29.110915 | -21.161023 | -18.834211 | 0.176794 | 36412 | -20.000502 | -13.322742 | 0.0000 | 113.128977 | 167.507029 | 170.939868 | 1.014572 | 36412 | 169.223053 | 27926 | 0.0000 | 166.792580 | 135.389366 | 138.853939 | 0.812162 | 36412 | 137.105863 | 24275 | 0.0000 | 168.815827 |
288 | -8.692104 | -6.688495 | 0.078765 | 36412 | -7.692815 | -9.064281 | 0.0000 | 97.668134 | 26.507106 | 27.097945 | 0.929458 | 36412 | 26.802432 | 26817 | 0.0000 | 28.836634 | 24.256693 | 24.848820 | 0.849750 | 36412 | 24.552943 | 24333 | 0.0000 | 28.894303 | -7.066694 | -4.880663 | 0.056051 | 36412 | -5.972256 | -9.064281 | 0.0000 | 106.550487 | 144.772551 | 148.116831 | 0.896616 | 36412 | 146.441059 | 26817 | 0.0000 | 163.326311 | 135.193177 | 138.534677 | 0.842841 | 36412 | 136.850696 | 24333 | 0.0000 | 162.368278 |
295 | -8.451073 | -6.487988 | 0.078553 | 36412 | -7.465578 | -9.965601 | 0.0000 | 95.038137 | 26.227839 | 26.810221 | 0.934812 | 36412 | 26.518982 | 26954 | 0.0000 | 28.368264 | 24.041599 | 24.631913 | 0.848641 | 36412 | 24.335941 | 24223 | 0.0000 | 28.676376 | -7.155538 | -4.998141 | 0.057940 | 36412 | -6.066644 | -9.965601 | 0.0000 | 104.705873 | 143.890838 | 147.193701 | 0.901082 | 36412 | 145.533611 | 26954 | 0.0000 | 161.509800 | 134.158886 | 137.431875 | 0.847661 | 36412 | 135.791678 | 24223 | 0.0000 | 160.195706 |
302 | -16.788075 | -14.767719 | 0.161465 | 36412 | -15.778916 | -11.469016 | 0.0000 | 97.723250 | 28.307275 | 28.901713 | 0.989892 | 36412 | 28.605463 | 27159 | 0.0000 | 28.897554 | 23.700006 | 24.285004 | 0.842108 | 36412 | 23.991484 | 24016 | 0.0000 | 28.489791 | -16.355329 | -14.187605 | 0.144177 | 36412 | -15.269975 | -11.469016 | 0.0000 | 105.911147 | 156.307454 | 159.633681 | 0.976922 | 36412 | 157.962497 | 27159 | 0.0000 | 161.694107 | 131.823590 | 135.068009 | 0.842044 | 36412 | 133.441677 | 24016 | 0.0000 | 158.473579 |
309 | 1.418960 | 3.344148 | 0.025434 | 36412 | 2.383509 | -3.689206 | 0.0000 | 93.714562 | 23.557635 | 24.129942 | 0.854020 | 36412 | 23.844322 | 25471 | 0.0000 | 27.920098 | 24.249008 | 24.833174 | 0.861610 | 36412 | 24.541294 | 24460 | 0.0000 | 28.483052 | 3.082298 | 5.098305 | 0.041662 | 36412 | 4.088201 | -3.689206 | 0.0000 | 98.126636 | 128.229731 | 131.351158 | 0.860392 | 36412 | 129.795773 | 25471 | 0.0000 | 150.856525 | 134.741474 | 137.993034 | 0.862254 | 36412 | 136.360685 | 24460 | 0.0000 | 158.144438 |
316 | -0.013441 | 1.855826 | 0.010124 | 36412 | 0.923626 | -5.561177 | 0.0538 | 91.233627 | 23.789861 | 24.355525 | 0.872778 | 36412 | 24.071679 | 25655 | 0.0000 | 27.580515 | 24.048350 | 24.635555 | 0.853537 | 36412 | 24.341760 | 24131 | 0.0000 | 28.518706 | 0.960639 | 2.936018 | 0.020219 | 36412 | 1.945900 | -5.561177 | 0.0001 | 96.242442 | 129.917547 | 132.995422 | 0.874101 | 36412 | 131.457393 | 25655 | 0.0000 | 150.391536 | 132.984073 | 136.195758 | 0.858729 | 36412 | 134.582157 | 24131 | 0.0000 | 156.722467 |
323 | -0.449092 | 1.424205 | 0.005395 | 36412 | 0.491027 | -6.331130 | 0.3084 | 91.022679 | 24.101156 | 24.664755 | 0.885505 | 36412 | 24.381483 | 25867 | 0.0000 | 27.533976 | 24.231400 | 24.821104 | 0.851950 | 36412 | 24.525066 | 24132 | 0.0000 | 28.786979 | 1.100410 | 3.045993 | 0.021909 | 36412 | 2.072926 | -6.331130 | 0.0000 | 94.615309 | 130.508716 | 133.535718 | 0.900117 | 36412 | 132.015099 | 25867 | 0.0000 | 146.664441 | 133.717705 | 136.963623 | 0.856707 | 36412 | 135.343844 | 24132 | 0.0000 | 157.981545 |
330 | 1.146250 | 3.013231 | 0.022953 | 36412 | 2.081317 | -6.006363 | 0.0000 | 90.677058 | 23.672634 | 24.226815 | 0.885906 | 36412 | 23.949209 | 25845 | 0.0000 | 27.033579 | 24.263309 | 24.854300 | 0.851714 | 36412 | 24.557815 | 24199 | 0.0000 | 28.833408 | 2.190789 | 4.138408 | 0.033151 | 36412 | 3.162892 | -6.006363 | 0.0000 | 95.407417 | 129.202581 | 132.246109 | 0.884858 | 36412 | 130.716175 | 25845 | 0.0000 | 147.725544 | 134.179053 | 137.425834 | 0.858697 | 36412 | 135.795209 | 24199 | 0.0000 | 158.140916 |
337 | -0.665498 | 1.200091 | 0.002967 | 36412 | 0.269062 | -6.174220 | 0.5729 | 90.687466 | 23.475149 | 24.033561 | 0.872412 | 36412 | 23.752620 | 25253 | 0.0000 | 27.226384 | 23.534540 | 24.126372 | 0.827962 | 36412 | 23.831297 | 23561 | 0.0000 | 28.783096 | 0.384737 | 2.323714 | 0.014247 | 36412 | 1.348729 | -6.174220 | 0.0061 | 94.664781 | 127.549702 | 130.581785 | 0.880071 | 36412 | 129.062425 | 25253 | 0.0000 | 146.649995 | 129.611536 | 132.863920 | 0.832246 | 36412 | 131.228241 | 23561 | 0.0000 | 157.679686 |
344 | 1.866044 | 3.735199 | 0.030736 | 36412 | 2.800551 | -4.232917 | 0.0000 | 91.114959 | 22.393966 | 22.952200 | 0.834181 | 36412 | 22.673676 | 24416 | 0.0000 | 27.180772 | 23.198702 | 23.787602 | 0.817531 | 36412 | 23.492597 | 23256 | 0.0000 | 28.736020 | 2.991303 | 4.924029 | 0.042242 | 36412 | 3.961977 | -4.232917 | 0.0000 | 93.793202 | 121.579390 | 124.571066 | 0.844111 | 36412 | 123.069395 | 24416 | 0.0000 | 145.797641 | 127.830699 | 131.044355 | 0.823465 | 36412 | 129.431613 | 23256 | 0.0000 | 157.179219 |
351 | -1.858871 | 0.008253 | 0.010175 | 36412 | -0.925162 | -6.039205 | 0.0520 | 90.927521 | 22.735632 | 23.308513 | 0.825718 | 36412 | 23.022386 | 24274 | 0.0000 | 27.881645 | 22.456868 | 23.048557 | 0.792501 | 36412 | 22.751856 | 22619 | 0.0000 | 28.708948 | -0.399530 | 1.523782 | 0.006084 | 36412 | 0.567723 | -6.039205 | 0.2471 | 93.309607 | 123.137885 | 126.190072 | 0.844187 | 36412 | 124.664052 | 24274 | 0.0000 | 147.673500 | 123.953709 | 127.203093 | 0.796727 | 36412 | 125.575713 | 22619 | 0.0000 | 157.614568 |
358 | -10.321498 | -8.460976 | 0.103887 | 36412 | -9.387045 | -9.878023 | 0.0000 | 90.357792 | 25.602566 | 26.200322 | 0.892425 | 36412 | 25.901071 | 26334 | 0.0000 | 29.023262 | 22.862387 | 23.450523 | 0.809888 | 36412 | 23.156166 | 23627 | 0.0000 | 28.591799 | -8.848608 | -6.928491 | 0.084137 | 36412 | -7.889462 | -9.878023 | 0.0000 | 93.769321 | 140.011507 | 143.215505 | 0.904927 | 36412 | 141.612132 | 26334 | 0.0000 | 156.490122 | 127.335053 | 130.578486 | 0.815545 | 36412 | 128.943081 | 23627 | 0.0000 | 158.106636 |
ds = 'default' # drawstyle
ds = 'steps-post' # drawstyle
weight = 'normal'
days = np.r_[0, np.cumsum(dfs['2019', 'm'].index.unique().daysinmonth.values)[:]]
if estimate == np.mean or estimate == np.nanmean:
desc = 'mean'
else:
desc = '50%'
sfrq = 'Daily'
if freq == 'd':
lw = 1
factor = np.ones(int(days[-1]))
elif freq == 'w':
lw = 3
factor = np.ones(int(days[-1]/7)) * 7
sfrq = 'Weekly'
elif freq == 'm':
lw = 3
factor = np.diff(days)
sfrq = 'Monthly'
def repeat_last(df, freq):
"""Repeat last point in data for plotting.
"""
x = df.iloc[-1]
if freq == 'd':
x.name = x.name + 1
df = pd.concat([df, x.to_frame().transpose()])
t = df.index
elif freq == 'w':
x.name = x.name + 7
df = pd.concat([df, x.to_frame().transpose()])
t = df.index
elif freq == 'm':
#x.name = x.name + 31
x.name = days[-1]
df = pd.concat([df, x.to_frame().transpose()])
#t = df.index - 31
t = days
return t, df
def plot(ax, t, df, c1, ds='default'):
"""General plot.
"""
if ds == 'steps-post':
ax.fill_between(t, df['ci_inf'], df['ci_sup'], label='', lw=lw+1,
color=c1, alpha=.3, clip_on=False, step='post')
else:
ax.fill_between(t, df['ci_inf'], df['ci_sup'], label='', lw=lw+1,
color=c1, alpha=.3, clip_on=False)
ax2 = sns.lineplot(x=t, y=df['mean'], color=c1, ci=None, alpha=1,
legend=False, lw=lw, ax=ax, clip_on=False, drawstyle=ds)
return ax2
def plot2(ax, axb, t, df, n, c1, c2, ds='default'):
"""General plot.
"""
if ds == 'steps-post':
ax.fill_between(t, df['ci_inf'], df['ci_sup'],
color=c1, alpha=.4, clip_on=False, step='post')
else:
ax.fill_between(t, df['ci_inf'], df['ci_sup'],
color=c1, alpha=.4, clip_on=False)
sns.lineplot(x=t, y=df['mean'], color=c1, ci=None, alpha=1,
legend=False, lw=lw+1, ax=ax, clip_on=False, drawstyle=ds)
axb.plot(t, n, color=c2, lw=lw, alpha=1, clip_on=False, drawstyle=ds)
for v, var in enumerate(variables):
fig = plt.figure(figsize=(13, 8))
gs = fig.add_gridspec(4, 1)
ax0 = fig.add_subplot(gs[0, 0])
ax1 = fig.add_subplot(gs[1, 0])
ax2 = fig.add_subplot(gs[2:, 0])
#plt.suptitle('{} long-distance running volume (all athletes from {})'.
# format(sfrq, country[0]), fontsize=16, c=c3, ha='center', y=.98)
for ax in [ax0, ax1, ax2]:
ax.axvline(days[3], c=colorbase, alpha=.8, ls=':', lw=1, label='')
ax.axvline(days[6], c=colorbase, alpha=.8, ls=':', lw=1, label='')
ax.axvline(days[9], c=colorbase, alpha=.8, ls=':', lw=1, label='')
ax.set_xlim([0, 365])
ax.spines['left'].set_position(('axes', -0.012))
t, var2019 = repeat_last(dfsdata[var+'2019'], freq)
t, var2020 = repeat_last(dfsdata[var+'2020'], freq)
# first plot
ax0.plot(t, var2019['nathletes'], color=color2019, lw=lw, alpha=1, clip_on=False,
drawstyle=ds, label='2019')
ax0.plot(t, var2020['nathletes'], color=color2020, lw=lw, alpha=1, clip_on=False,
drawstyle=ds, label='2020')
ax0.text(0.01, 0.9, 'A', ha='right', weight=weight,
fontsize=14, c='k', transform=ax0.transAxes)
ax0.set_ylabel('Number of\nathletes', c=colorbase, fontsize=16)
handles, labels = ax0.get_legend_handles_labels()
ax0.legend(handles, labels, frameon=False, loc='lower left')
# second plot
plot(ax1, t, var2019, color2019, ds)
plot(ax1, t, var2020, color2020, ds)
ax1.text(0.01, 0.9, 'B', ha='right', weight=weight,
fontsize=14, c='k', transform=ax1.transAxes)
ax1.set_ylabel('{} [{}]\nMean and 95%CI'.format(var.capitalize(), units[v]),
c=colorbase, fontsize=16)
# third plot
ax2b = ax2.twinx()
ax2.axhline(0, c=colorbase, alpha=.8, lw=2)
t, vard = repeat_last(dfsdata[var], freq)
plot2(ax2, ax2b, t, vard, vard['nathletes'].values, colorvar, colorn, ds)
ax2.text(0.01, 0.95, 'C', ha='right', weight=weight,
fontsize=14, c='k', transform=ax2.transAxes)
ax2.tick_params(axis='x', colors=colorbase)
ax2.tick_params(axis='y', colors=colorvar)
ax2.spines['left'].set_color(colorvar)
ax2.spines['bottom'].set_position(('axes', -0.15))
text = '{} difference [%]\nMean and 95%CI'.format(var.capitalize())
ax2.set_ylabel(text, color=colorvar, fontsize=16)
ax2.tick_params(axis='both', which='major', labelsize=14)
text = 'Number of athletes difference [%]'.format(sfrq)
ax2b.set_ylabel(text, rotation=-90, color=colorn, fontsize=16)
ax2b.yaxis.set_label_coords(1.08, .5)
ax2b.tick_params(axis='both', which='major', labelsize=14)
ax2b.spines['bottom'].set_visible(False)
ax2b.spines['top'].set_visible(False)
ax2b.spines['left'].set_visible(False)
ax2b.spines['right'].set_color(colorn)
ax2b.spines['right'].set_position(('axes', 1.01))
ax2b.tick_params(axis='y', colors=colorn)
ax2b.grid(False, axis='both')
# plot coronavirus policy response index
colori = colors[4]
ax2c = ax2.twinx()
c19idx.index = dfsdata.index
t, c19idx2 = repeat_last(c19idx, freq)
ax2c.plot(t, c19idx2['si'], color=colorind, alpha=.8, lw=lw+2, ls='-',
clip_on=False, drawstyle=ds)
ax2c.set_ylim([100, -100])
ax2c.set_yticks([0, 50, 100])
ax2c.spines['bottom'].set_visible(False)
ax2c.spines['top'].set_visible(False)
ax2c.spines['left'].set_visible(False)
ax2c.spines['right'].set_color(colorind)
ax2c.spines['right'].set_position(('axes', 1.11))
ax2c.tick_params(axis='both', which='major', labelsize=14)
ax2c.set_ylabel('2020 stringency index', rotation=-90, color=colorind, fontsize=16)
ax2c.tick_params(axis='y', colors=colorind)
ax2c.yaxis.set_label_coords(1.17, .45)
# pvalues plot
pvalidx = np.where(dfsdata[var]['pvalue'] <= alphaS)[0]
pval = (t[pvalidx] + factor[pvalidx]/2, )
ax2.eventplot(-np.ones_like(pval)*72, colors=colorvar, lineoffsets=pval,
linelengths=np.atleast_2d(factor[pvalidx]), orientation='vertical',
linewidth=7, alpha=0.4, clip_on=False)
# effect sizes plot
esi = np.where(dfsdata[var]['cohensd'] > 0.2)[0]
es = (t[esi] + factor[esi]/2, )
ax2.eventplot(-np.ones_like(es)*68, colors=colorvar, lineoffsets=es,
linelengths=np.atleast_2d(factor[esi]), orientation='vertical',
linewidth=5, alpha=1, clip_on=False)
if country[1] != 'all':
ax0.text(1.1, .8, 'Number of athletes', ha='center', weight=weight,
fontsize=14, c=colorbase, transform=ax0.transAxes)
ax0.text(1.03, .6, '2019:', ha='left', weight=weight,
fontsize=14, c=color2019, transform=ax0.transAxes)
ax0.text(1.1, .6, '{:,}'.format(nruns['2019', 'd'].size),
ha='left', weight=weight, fontsize=14, c=color2019, transform=ax0.transAxes)
ax0.text(1.03, .4, '2020:', ha='left', weight=weight,
fontsize=14, c=color2020, transform=ax0.transAxes)
ax0.text(1.1, .4, '{:,}'.format(nruns['2020', 'd'].size),
ha='left', weight=weight, fontsize=14, c=color2020, transform=ax0.transAxes)
ax1.text(1.09, .8, 'Mean {}'.format(var), ha='center', weight=weight,
fontsize=14, c=colorbase, transform=ax1.transAxes)
ax1.text(1.03, .6, '2019:', ha='left', weight=weight,
fontsize=14, c=color2019, transform=ax1.transAxes)
ax1.text(1.1, .6, '{:.1f} {}'.format(
np.round(dfs_stat['2019', freq][desc][var], 1), units[v]),
ha='left', weight=weight, fontsize=14, c=color2019, transform=ax1.transAxes)
ax1.text(1.03, .4, '2020:', ha='left', weight=weight,
fontsize=14, c=color2020, transform=ax1.transAxes)
ax1.text(1.1, .4, '{:.1f} {}'.format(
np.round(dfs_stat['2020', freq][desc][var], 1), units[v]),
ha='left', weight=weight, fontsize=14, c=color2020, transform=ax1.transAxes)
ax2.text(-.01, -0.13, 'p value < 0.001', ha='right',
weight=weight, fontsize=13, c=colorbase, transform=ax2.transAxes)
ax2.text(-.01, -0.07, 'effect size > 0.2', ha='right',
weight=weight, fontsize=13, c=colorbase, transform=ax2.transAxes)
ax2c.grid(False, axis='both')
if freq != 'd':
ax2.set_ylim([-60, 60])
ax2.set_yticks([-40, -20, 0, 20, 40])
ax2b.set_ylim([-30, 30])
ax2b.set_yticks([-20, -10, 0, 10, 20])
for ax in [ax0, ax1, ax2]:
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
ax.set_xticklabels([])
ax.set_xlabel('')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.grid(False, axis='both')
ax.tick_params(axis='both', which='major', labelsize=14)
ax.set_xticks(days)
labels = [' ' + m[0] for m in months]
labels.append('')
#ax0.set_xticklabels(labels, rotation=0, fontsize=14, ha='left')
#ax1.set_xticklabels(labels, rotation=0, fontsize=14, ha='left')
labels = [m[0:3] for m in months]
labels.append('')
ax2.set_xticklabels(labels, rotation=0, fontsize=14, ha='left')
ax2.tick_params(axis='both', which='major', labelsize=14)
labels = [m[0:3] for m in months]
labels.append('')
ax2.set_xlabel('Month of the year', c=colorbase, fontsize=16)
ax2.xaxis.set_ticks_position('bottom')
ax2.spines['bottom'].set_color(colorbase)
ax2.set_xticklabels(labels, rotation=0, fontsize=14, ha='left')
fig.align_ylabels([ax0, ax1, ax2])
ax0.margins(y=.2)
ax1.margins(y=.2)
plt.subplots_adjust(left=0.15, bottom=0.15, right=0.85, top=0.9, wspace=0.1, hspace=0.15)
fig.savefig(path2 / 'figure{}_{}_{}_{}.png'.format(v+1, var, freq, country[1]), dpi=200)
plt.show()
Figures. Comparison between 2019 and 2020 of long-distance running volume (distance and duration) and number of athletes. Blue color denotes the difference in athletes' weekly running volume (2020 - 2019) in each week of the year, normalized by the mean weekly running volume in 2019 (mean among all athletes; 95% confidence interval). Red color denotes the difference in the number of athletes running per week in each week of the year, normalized by the mean number of athletes running per week in 2019. The numbers in the upper left corner indicate the mean weekly running volume in 2019 and 2020 by athletes. In the upper right are the number of athletes running per week, in 2019 and 2020. At the bottom, the orange horizontal bars indicate a small effect size (between 0.2 and 0.5) and the light blue horizontal bars indicate a statistical difference (p<0.001) between the corresponding weeks of 2019 and 2020 for the weekly running volume. The green curve indicates the mean COVID-19 government response stringency index during 2020, weighted by the number of athletes in the country.