"Od czasu kiedy kupiłam sobie Fitbita, jestem zafascynowana ile przydatnych informacji o moim zdrowiu i życiu dostarcza. Nie byłabym sobą, gdybym pozostała tylko przy informacjach z algorytmów appki producenta. Musiałam ściągnąć dane źródłowe i sprawdzić z czym jeszcze korelują mój sen i tętno. W ramach prezentacji pokażę hands-on analizę danych z trackera aktywności Fitbit w języku Python - tak, żeby każdy mógł później przeanalizować dane o swoim zdrowiu."
1 of 36
Download to read offline
More Related Content
infoShare AI Roadshow 2018 - Magdalena Wójcik (Data Love) - Data Science na danych z trackera aktywności - case
5. Jakich danych dostarcza Fitbit?Jakich danych dostarcza Fitbit?
Liczba kroków, pięter na które się weszło, przebytych kilometrów.
Liczba spalonych kalorii w ciągu dnia.
Tętno spoczynkowe, tętno w danym momencie.
Długość i jakość snu.
Dane pochodzą z czujników:
Akcelerometru
Barometru
Żyroskopu
Fotoplezmatografu
Nie mamy dostępu do bezpośredniego sygnału z czujników z poziomu Web API.
6. Fotopletyzmogra a (PPG)Fotopletyzmogra a (PPG)
Metoda optycznego pomiaru
zmian przepływu krwi przez
naczynia obwodowe położone
blisko powierzchni ciała, może
być stosowana do pomiaru
szybkości pracy serca.
Fitbit używa zielonych LEDów i
fotodiody do pomiaru odbijanego
światła, a dzięki temu pojemności
naczyń krwionośnych pod skórą.
13. In [11]: meteo_daily = pd.read_csv("data/Dane meteorologiczne.csv", index_col=[0], parse_
dates=[0])
meteo_daily = meteo_daily.fillna(0)
meteo_daily.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 113 entries, 2018-07-11 to 2018-10-31
Data columns (total 17 columns):
Średnia temperatura powietrza 113 non-null float64
Maksymalna temperatura powietrza 113 non-null float64
Minimalna temperatura powietrza 113 non-null float64
Minimalna temperatura powietrza przy gruncie 113 non-null float64
Średnia wilgotność powietrza 113 non-null float64
Średnia prężność pary wodnej 113 non-null float64
Średnie zachmurzenie 113 non-null float64
Średnia prędkość wiatru 113 non-null float64
Ciśnienie na poziomie morza 113 non-null float64
Ciśnienie na poziomie stacji 113 non-null float64
Dobowa suma opadu 113 non-null float64
Opad - dzień 113 non-null float64
Opad - noc 113 non-null float64
Usłonecznienie 113 non-null float64
Czas trwania opadu deszczu 113 non-null float64
Czas trwania rosy 113 non-null float64
Czas trwania burzy 113 non-null float64
dtypes: float64(17)
memory usage: 15.9 KB
14. Czy wszystkie analizowane szeregi są stacjonarne?Czy wszystkie analizowane szeregi są stacjonarne?
Stacjonarny szereg czasowy - szereg w którym wartość średnia, wariancja oraz funkcja
autokorelacji nie zmieniają się wraz ze zmianą czasu.
16. Rozszerzony test Dickeya-Fullera (Augmented Dickey-Rozszerzony test Dickeya-Fullera (Augmented Dickey-
Fuller test)Fuller test)
Test statystyczny, polegający na próbie dopasowania do danych modelu
autoregresyjnego, uwzględniający dwie hipotezy:
: Szereg jest niestacjonarny.
: Szereg jest stacjonarny.
Przy wyniku hipoteza zerowa jest odrzucana - szereg jest
stacjonarny.
H0
H1
p − value < 0.05
17. In [12]: import statsmodels.tsa.stattools as ts
rhr_series = rhr_daily["value.restingHeartRate"].values
result = ts.adfuller(rhr_series)
print("Wynik testu dla tętna spoczynkowegonp-value: {:.24f}".format(result[1]))
sleep_series = data_sleep["efficiency"].fillna(0).values
result = ts.adfuller(sleep_series)
print("Wynik testu dla efektywności snunp-value: {:.24f}".format(result[1]))
Wynik testu dla tętna spoczynkowego
p-value: 0.026188396618426579981476
Wynik testu dla efektywności snu
p-value: 0.000000000019042035089119
18. In [13]: meteo_adf = np.zeros(len(meteo_daily.columns))
for i, column in enumerate(meteo_daily.columns):
meteo_series = meteo_daily[column].fillna(0).values
adf = ts.adfuller(meteo_series)[1]
meteo_adf[i] = adf
meteo_adf_df = pd.DataFrame(meteo_adf, index=meteo_daily.columns,
columns=["p-value"])
meteo_adf_df.sort_values(by="p-value", ascending=False, inplace=True)
meteo_adf_df.style.format("{:.6f}")
Out[13]: p-value
Minimalna temperatura powietrza przy gruncie 0.867639
Minimalna temperatura powietrza 0.859623
Średnia prężność pary wodnej 0.699345
Średnia temperatura powietrza 0.614118
Maksymalna temperatura powietrza 0.395975
Czas trwania burzy 0.017540
Ciśnienie na poziomie morza 0.004599
Ciśnienie na poziomie stacji 0.003533
Średnia wilgotność powietrza 0.001089
Czas trwania opadu deszczu 0.000424
Średnie zachmurzenie 0.000000
Usłonecznienie 0.000000
Średnia prędkość wiatru 0.000000
Czas trwania rosy 0.000000
Opad - dzień 0.000000
Dobowa suma opadu 0.000000
Opad - noc 0.000000
19. In [14]: from statsmodels.tsa.seasonal import seasonal_decompose
def meteo_decompose(dataset, column):
result = seasonal_decompose(meteo_daily[column], model="additive", )
meteo_daily[column + " - resid"] = result.resid
meteo_daily.drop(column, axis=1, inplace=True)
return dataset, result
meteo_daily, result = meteo_decompose(meteo_daily, "Średnia temperatura powietrz
a")
result.plot()
pyplot.show()
25. In [42]: corr_rhr.stack().abs().sort_values(ascending=False)
Out[42]: Usłonecznienie 6 0.404034
7 0.392621
Średnia prędkość wiatru 5 0.343960
Ciśnienie na poziomie morza -8 0.331546
Średnia wilgotność powietrza 6 0.330481
Średnia prędkość wiatru 4 0.328771
Ciśnienie na poziomie morza -7 0.324229
Ciśnienie na poziomie stacji -8 0.322160
Ciśnienie na poziomie morza -6 0.319641
Ciśnienie na poziomie stacji -7 0.315570
-6 0.310706
Średnie zachmurzenie 6 0.303247
Średnia prędkość wiatru 6 0.302663
Czas trwania opadu deszczu 6 0.301615
Usłonecznienie 5 0.301121
8 0.297127
Czas trwania burzy 2 0.297096
Ciśnienie na poziomie morza -5 0.296600
-9 0.292152
Ciśnienie na poziomie stacji -5 0.286841
Usłonecznienie 9 0.285268
Średnia prędkość wiatru -8 0.284111
Ciśnienie na poziomie stacji -9 0.280799
Średnie zachmurzenie 7 0.280593
Czas trwania opadu deszczu 8 0.278038
Średnia wilgotność powietrza -10 0.277524
7 0.275640
Usłonecznienie 4 0.274867
Ciśnienie na poziomie morza 9 0.270913
Czas trwania opadu deszczu 7 0.270538
...
Minimalna temperatura powietrza - resid -1 0.008364
-6 0.008314
Średnia temperatura powietrza - resid 2 0.007613
26. Maksymalna temperatura powietrza - resid 1 0.007468
Średnia temperatura powietrza - resid 3 0.007448
Średnia prężność pary wodnej - resid 8 0.007151
Średnia prędkość wiatru 10 0.006572
Minimalna temperatura powietrza - resid 7 0.005815
-10 0.005676
Średnia prędkość wiatru 9 0.005628
Minimalna temperatura powietrza przy gruncie - resid -1 0.005619
Opad - dzień -10 0.005463
Minimalna temperatura powietrza przy gruncie - resid 8 0.004637
Dobowa suma opadu 4 0.004316
Opad - noc 3 0.003697
Minimalna temperatura powietrza przy gruncie - resid -10 0.003537
Minimalna temperatura powietrza - resid -7 0.003211
Dobowa suma opadu 2 0.002903
Średnia prężność pary wodnej - resid -9 0.002869
Minimalna temperatura powietrza przy gruncie - resid -3 0.002641
Średnia temperatura powietrza - resid -4 0.002474
Maksymalna temperatura powietrza - resid 0 0.002445
Ciśnienie na poziomie morza 0 0.002042
3 0.001826
Czas trwania rosy -8 0.001703
Czas trwania burzy -10 0.001640
Średnia temperatura powietrza - resid 10 0.001429
Maksymalna temperatura powietrza - resid -4 0.001039
Średnia temperatura powietrza - resid 1 0.000645
Maksymalna temperatura powietrza - resid 2 0.000056
Length: 357, dtype: float64
27. In [49]: sns.set()
plt.plot(meteo_daily.index, meteo_daily["Usłonecznienie"].shift(6).apply(lambda
x: x + 40))
plt.plot(meteo_daily.index, meteo_daily["Ciśnienie na poziomie morza"].shift(-8)
.apply(lambda x: x - 900))
plt.plot(meteo_daily.index, meteo_daily["Średnia prędkość wiatru"].shift(5))
plt.plot(rhr_daily.index, rhr_daily["value.restingHeartRate"])
plt.legend(["Usłonecznienie", "Ciśnienie na poziomie morza", "Średnia prędkość w
iatru", "Tętno spoczynkowe"])
Out[49]: <matplotlib.legend.Legend at 0x7fdd41a07b70>
30. In [50]: corr_sleep_efficiency.stack().abs().sort_values(ascending=False)
Out[50]: Średnia prędkość wiatru 6 0.301546
Czas trwania burzy -10 0.242508
Czas trwania rosy -5 0.225645
-3 0.222534
Opad - dzień 1 0.221495
Czas trwania burzy -4 0.220298
Dobowa suma opadu 1 0.219600
Średnia prężność pary wodnej - resid 1 0.205617
-3 0.197595
Minimalna temperatura powietrza przy gruncie - resid 6 0.189702
Opad - noc 5 0.188261
Średnia prężność pary wodnej - resid -4 0.188176
Minimalna temperatura powietrza - resid -4 0.187696
Czas trwania rosy 0 0.185332
Opad - dzień 7 0.184611
Czas trwania burzy -6 0.183412
Średnia prężność pary wodnej - resid -10 0.183362
Dobowa suma opadu 7 0.179223
Ciśnienie na poziomie stacji -1 0.175914
Średnia prężność pary wodnej - resid 7 0.175660
Średnia prędkość wiatru -10 0.175016
Minimalna temperatura powietrza przy gruncie - resid 0 0.174345
Ciśnienie na poziomie morza -1 0.173830
Średnia prędkość wiatru 1 0.173023
Opad - noc 9 0.170768
Średnia wilgotność powietrza -10 0.167220
Opad - dzień 2 0.167063
Maksymalna temperatura powietrza - resid 2 0.161642
Czas trwania rosy 2 0.160725
Czas trwania opadu deszczu 7 0.160224
...
Średnia prężność pary wodnej - resid -9 0.009866
Minimalna temperatura powietrza przy gruncie - resid -10 0.009702
Czas trwania rosy 7 0.008342
31. Ciśnienie na poziomie morza 10 0.008016
Średnia prężność pary wodnej - resid 3 0.007959
Opad - dzień -6 0.007406
Średnia temperatura powietrza - resid -10 0.007068
Średnia prędkość wiatru -6 0.007031
Opad - dzień 8 0.006915
Minimalna temperatura powietrza przy gruncie - resid -2 0.005759
Czas trwania burzy 10 0.005480
Średnia prężność pary wodnej - resid -2 0.003840
Opad - noc 6 0.003700
Czas trwania opadu deszczu 2 0.003075
Opad - noc -6 0.003004
Usłonecznienie -3 0.002803
Minimalna temperatura powietrza - resid -8 0.002595
Dobowa suma opadu -4 0.002306
Opad - dzień -3 0.002302
Średnia prędkość wiatru -9 0.001755
-8 0.001745
Ciśnienie na poziomie stacji -5 0.001464
Maksymalna temperatura powietrza - resid -5 0.001385
-6 0.001379
Czas trwania rosy 3 0.001218
Średnie zachmurzenie -9 0.000956
-8 0.000954
Ciśnienie na poziomie morza -5 0.000938
Opad - dzień -7 0.000821
Dobowa suma opadu -6 0.000520
Length: 357, dtype: float64
32. In [51]: sns.set()
plt.plot(meteo_daily.index, meteo_daily["Średnia prędkość wiatru"].shift(-4))
plt.plot(meteo_daily.index, meteo_daily["Czas trwania burzy"].shift(-10))
plt.plot(meteo_daily.index, meteo_daily["Czas trwania rosy"].shift(-5).apply(lam
bda x: x + 10))
plt.plot(data_sleep.index, data_sleep["efficiency"].apply(lambda x: x - 60))
plt.legend(["Średnia prędkość wiatru", "Czas trwania burzy", "Czas trwania rosy"
, "Efektywność snu"])
Out[51]: <matplotlib.legend.Legend at 0x7fdd41a2f4a8>
33. To czy jestem meteoropatką?To czy jestem meteoropatką?
35. PodsumowaniePodsumowanie
Szeregi okazały się być słabo skorelowane, ale widoczne były pewne wzorce.
Do potwierdzenia lub obalenia hipotezy potrzebne są dalsze analizy. Potencjalne kierunki
badań:
Uwzględeninie poziomu aktywności zycznej
Analiza danych na poziomie godzin lub minut
Ponowna analiza po uzyskaniu większej liczby próbek