[fitbit] 6.Fitbit APIで一週間分の睡眠データを取得してまとめて表示

fitbit

はじめに

fitbitとは、心拍数、歩数や睡眠をトラッキングするために腕に着用するタイプのスマートウォッチです。ここでは、Fitbit APIを使って一週間分の睡眠データを取得してmatplotlibでまとめて表示する方法を解説します。

手順

APIの登録など

その1を参照してください。

[fitbit] 1. PythonでFitbit APIを使ってデータ取得 その1 アプリの登録とtokenの取得
fitbitとは、心拍数、歩数や睡眠をトラッキングするために腕に着用するタイプのスマートウォッチです。日々の健康状態を把握するのにとても役立っています。ここでは、Fitbit APIを使ってデータを取得するために、アプリの登録からtokenの取得まで解説します。

fitbit-pythonのインストールなど

その2を参照してください。

[fitbit] 2. PythonでFitbit APIを使ってデータ取得 その2 fitbit-pythonによる睡眠データの取得とmatplotlibによる表示
fitbitとは、心拍数、歩数や睡眠をトラッキングするために腕に着用するタイプのスマートウォッチです。日々の健康状態を把握するのにとても役立っています。ここでは、アプリの登録からtokenの取得までを解説したその1の続きとして、Fitbit APIを使って睡眠データを取得してmatplotlibで表示するところまで解説します。

モジュールのインポートなど

import fitbit
from ast import literal_eval
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np
import seaborn as sns
import datetime as dt
plt.style.use('bmh')

バージョン

#version
import matplotlib
print(matplotlib.__version__)
3.4.2
print(fitbit.__version__)
0.3.1
print(pd.__version__)
1.2.4
print(np.__version__)
1.20.3
print(sns.__version__)
0.11.1

APIの認証

CLIENT_ID, tokenなどを定義

CLIENT_ID = "####"
CLIENT_SECRET = "#################"
TOKEN_FILE = "token.txt"
tokens = open(TOKEN_FILE).read()
token_dict = literal_eval(tokens)
access_token = token_dict['access_token']
refresh_token = token_dict['refresh_token']

その1で取得したCLIENT_IDとCLIENT_SECRETとtoken.txtをここで使います。token.txtは実行ファイルと同じ場所に置いておきます。

認証

def updateToken(token):
f = open(TOKEN_FILE, 'w')
f.write(str(token))
f.close()
return
client = fitbit.Fitbit(CLIENT_ID, CLIENT_SECRET,
access_token = access_token, refresh_token = refresh_token, refresh_cb = updateToken)

fitbit.Fitbit()により、認証を行います。updateToken関数はtokenの更新用の関数でrefresh_cbupdateTokenとすることでtokenが期限切れの際に随時更新してくれるようになります。

1週間分のデータの取得

DATE = "2021-05-27"
DATE = dt.datetime.strptime(DATE, '%Y-%m-%d')
#1週間分のデータの取得
data_1w=[]
for i in range(7):
DATE_ = DATE+ dt.timedelta(days=i)
data_sleep = client.sleep(DATE_)
data_sleep_ = data_sleep["sleep"][0]["levels"]["data"]
data_sleep_ = pd.DataFrame.from_dict(data_sleep_)
data_sleep_.index=pd.to_datetime(data_sleep_["dateTime"])
data_1w.append(data_sleep_)

DATE+ dt.timedelta(days=i)で日付を一日単位でずらしながら、client.sleep(DATE_)により睡眠データが入手します。取得したデータはpd.DataFrame.from_dictによりデータフレームにし、リストに格納していきます。

リストの最初のデータフレームは以下のようになっています。

data_1w[0]
"""
dateTime level seconds
dateTime
2021-05-26 22:43:00 2021-05-26T22:43:00.000 wake 300
2021-05-26 22:48:00 2021-05-26T22:48:00.000 light 1110
2021-05-26 23:06:30 2021-05-26T23:06:30.000 deep 390
2021-05-26 23:13:00 2021-05-26T23:13:00.000 light 2520
2021-05-26 23:55:00 2021-05-26T23:55:00.000 deep 420
2021-05-27 00:02:00 2021-05-27T00:02:00.000 light 4200
2021-05-27 01:12:00 2021-05-27T01:12:00.000 rem 270
2021-05-27 01:16:30 2021-05-27T01:16:30.000 light 1050
2021-05-27 01:34:00 2021-05-27T01:34:00.000 wake 360
2021-05-27 01:40:00 2021-05-27T01:40:00.000 light 2880
2021-05-27 02:28:00 2021-05-27T02:28:00.000 rem 270
2021-05-27 02:32:30 2021-05-27T02:32:30.000 light 750
2021-05-27 02:45:00 2021-05-27T02:45:00.000 rem 1560
2021-05-27 03:11:00 2021-05-27T03:11:00.000 light 210
2021-05-27 03:14:30 2021-05-27T03:14:30.000 wake 330
2021-05-27 03:20:00 2021-05-27T03:20:00.000 light 3780
2021-05-27 04:23:00 2021-05-27T04:23:00.000 deep 420
2021-05-27 04:30:00 2021-05-27T04:30:00.000 light 2340
2021-05-27 05:09:00 2021-05-27T05:09:00.000 rem 360
2021-05-27 05:15:00 2021-05-27T05:15:00.000 light 870
2021-05-27 05:29:30 2021-05-27T05:29:30.000 wake 660
2021-05-27 05:40:30 2021-05-27T05:40:30.000 light 270
2021-05-27 05:45:00 2021-05-27T05:45:00.000 wake 300
2021-05-27 05:50:00 2021-05-27T05:50:00.000 light 330
"""

睡眠のレベルを数値化

#レベルを数値化
for i in range(7):
data_1w[i].loc[data_1w[i]['level']=="wake","level_int"]= 3
data_1w[i].loc[data_1w[i]['level']=="rem","level_int"]= 2
data_1w[i].loc[data_1w[i]['level']=="light","level_int"]= 1
data_1w[i].loc[data_1w[i]['level']=="deep","level_int"]= 0
data_1w[i] = data_1w[i].astype({'level_int': 'int'})

睡眠のレベルデータを数値データに変換します。

表示範囲の設定

#x軸表示範囲
xlim0=np.array([dt.datetime(2021,5,26,22,0,0),dt.datetime(2021,5,27,8,0,0)])
xlim1 = xlim0+dt.timedelta(days=1)
xlim2 = xlim1+dt.timedelta(days=1)
xlim3 = xlim2+dt.timedelta(days=1)
xlim4 = xlim3+dt.timedelta(days=1)
xlim5 = xlim4+dt.timedelta(days=1)
xlim6 = xlim5+dt.timedelta(days=1)
xlims = [xlim0,xlim1,xlim2,xlim3,xlim4,xlim5,xlim6]

それぞれの日付に対して22:00から8:00までデータを表示するために表示範囲のデータをdatetime形式で作成しておきます。

1週間分の睡眠データの表示

fig,ax=plt.subplots(7,1,dpi=100,figsize=(6,10))
ax= ax.ravel()
[ax[i].step(data_1w[i].index.values, data_1w[i]["level_int"].values,"-",where='post',lw=2) for i in range(7)]
[ax[i].text(0.05, 1.1, xlims[i][1].strftime('%m/%d'), horizontalalignment='center',verticalalignment='center', transform=ax[i].transAxes) for i in range(7)]
[ax[i].set_xlim(xlims[i]) for i in range(7)]
for a in ax:
locator = mdates.AutoDateLocator()
formatter = mdates.DateFormatter("%H:%M")
a.xaxis.set_major_locator(locator)
a.xaxis.set_major_formatter(formatter)
a.set(yticks=np.arange(4),yticklabels=["Deep","Light","Rem","Wake"])
ax[6].set(xlabel="Time")
ax[3].set(ylabel="Sleep level")
i=2
ax[i].text(0.05, 1.1, xlims[i][1].strftime('%m/%d'), horizontalalignment='center',verticalalignment='center', transform=ax[i].transAxes, color="b")
i=3
ax[i].text(0.05, 1.1, xlims[i][1].strftime('%m/%d'), horizontalalignment='center',verticalalignment='center', transform=ax[i].transAxes, color="r")
plt.tight_layout()
plt.savefig("sleep_1w.png",dpi=130)
plt.show()

ax[i].step()でそれぞれの日の睡眠データを順次プロットしていきます。
ax[i].text()でそれぞれのプロットの日付を左上に表示します。
ax[i].set_xlim()でx軸の表示範囲を調整します。
全てリスト内包で処理しています。

x軸の表示形式については、mdates.DateFormatter(“%H:%M”)により時間と分の形式で表示できるようになります。

i=2
ax[i].text(0.05, 1.1, xlims[i][1].strftime('%m/%d'), horizontalalignment='center',verticalalignment='center', transform=ax[i].transAxes, color="b")
i=3
ax[i].text(0.05, 1.1, xlims[i][1].strftime('%m/%d'), horizontalalignment='center',verticalalignment='center', transform=ax[i].transAxes, color="r")

土曜を青、日曜の日付を赤にしています。

コードをダウンロード(.pyファイル)

コードをダウンロード(.ipynbファイル)

参考

Overview — Python-Fitbit 0.3.0 documentation
Fitbit Development: Sleep
You'll fit in here. Using JavaScript, CSS, and SVG, developers now have a fast, easy way to build apps and clock faces f...

コメント