2023/10/10
前回から時間が空いてしまいました・・。前回は、睡眠のデータを詳しく見てきて、その質(スコア)が「前日の安静時の心拍数」や「寝ている時の寝返りを繰り返す割合」にも関係しているような知見が得られました。今回は睡眠に関する詳しいデータを眺めてみようと思います。
Fitbitの詳しい睡眠データはダウンロードしたデータファイルの中に、1か月単位のjsonファイル(sleep-YYYY-MM-DD.json)に保存されていました。このjsonファイルの構造が分かりにくかったので、ChatGPTに聞いてみました。ちなみにjsonファイルの中身はこんな感じです。
[{
"logId" : XXXXXXXXXX,
"dateOfSleep" : "2023-08-10",
"startTime" : "2023-08-09T22:52:30.000",
"endTime" : "2023-08-10T04:51:00.000",
"duration" : 21480000,
"minutesToFallAsleep" : 0,
"minutesAsleep" : 317,
"minutesAwake" : 41,
"minutesAfterWakeup" : 0,
"timeInBed" : 358,
"efficiency" : 88,
"type" : "stages",
"infoCode" : 0,
"logType" : "auto_detected",
"levels" : {
"summary" : {
"deep" : {
"count" : 3,
"minutes" : 57,
"thirtyDayAvgMinutes" : 45
},
"wake" : {
"count" : 26,
"minutes" : 41,
"thirtyDayAvgMinutes" : 53
},
"light" : {
"count" : 21,
"minutes" : 171,
"thirtyDayAvgMinutes" : 186
},
"rem" : {
"count" : 8,
"minutes" : 89,
"thirtyDayAvgMinutes" : 79
}
},
"data" : [{
"dateTime" : "2023-08-09T22:52:30.000",
"level" : "wake",
"seconds" : 240
},{
"dateTime" : "2023-08-09T22:56:30.000",
"level" : "light",
"seconds" : 480
},
・・・
中略
・・・
{
"dateTime" : "2023-08-10T04:49:30.000",
"level" : "wake",
"seconds" : 90
}]
},
"mainSleep" : true
},{
"logId" : XXXXXXXXXX,
"dateOfSleep" : "2023-07-30",
"startTime" : "2023-07-30T13:07:30.000",
"endTime" : "2023-07-30T14:21:00.000",
"duration" : 4380000,
"minutesToFallAsleep" : 0,
"minutesAsleep" : 65,
"minutesAwake" : 8,
"minutesAfterWakeup" : 0,
"timeInBed" : 73,
"efficiency" : 89,
"type" : "classic",
"infoCode" : 2,
"logType" : "auto_detected",
"levels" : {
"summary" : {
"restless" : {
"count" : 2,
"minutes" : 8
},
"awake" : {
"count" : 0,
"minutes" : 0
},
"asleep" : {
"count" : 0,
"minutes" : 65
}
},
"data" : [{
"dateTime" : "2023-07-30T13:07:30.000",
"level" : "restless",
"seconds" : 60
},{
"dateTime" : "2023-07-30T13:08:30.000",
"level" : "asleep",
"seconds" : 2040
},{
"dateTime" : "2023-07-30T13:42:30.000",
"level" : "restless",
"seconds" : 420
},{
"dateTime" : "2023-07-30T13:49:30.000",
"level" : "asleep",
"seconds" : 1860
}]
},
"mainSleep" : false
}
]
ChatGPT曰く、
添付されているJSONファイルは、特定の夜の睡眠データを含んでいます。以下に構造の説明を示します:
トップレベルの構造は、1つの辞書要素を含むリストです。
辞書内にはいくつかのキーと値のペアがあります:
"logId":睡眠ログの数値識別子。
"dateOfSleep":睡眠の日付("YYYY-MM-DD"形式)。
"startTime":睡眠の開始時刻("YYYY-MM-DDTHH:MM:SS.sss"形式)。
"endTime":睡眠の終了時刻("YYYY-MM-DDTHH:MM:SS.sss"形式)。
"duration":睡眠の期間(ミリ秒)。
"minutesToFallAsleep":眠りに落ちるのにかかった時間(分)。
"minutesAsleep":実際の睡眠時間(分)。
"minutesAwake":夜間の全体の覚醒時間(分)。
"minutesAfterWakeup":起床後の時間(分)。
"timeInBed":ベッドでの総時間(分)。
"efficiency":睡眠効率のパーセンテージ。
"type":睡眠データのタイプ(この場合は "stages")。
"infoCode":情報コード。
"logType":ログのタイプ(この場合は "auto_detected")。
"levels":睡眠ステージの概要と詳細データを含む辞書。
"mainSleep":メインの睡眠かどうかを示すブール値。
"levels"辞書内には2つのキーと値のペアがあります:
"summary":異なる睡眠ステージ(深い睡眠、覚醒、軽い睡眠、REM)の要約データを含む辞書。
"data":日付と時間を含む詳細な睡眠ステージのデータのリスト。
"summary"辞書内には、各睡眠ステージに対して4つのキーと値のペアがあります:
"count":この睡眠ステージのインスタンスの数。
"minutes":この睡眠ステージで過ごした合計時間(分)。
"thirtyDayAvgMinutes":この睡眠ステージの30日間の平均時間(分)。
"data"リストには、各辞書に以下のキーと値のペアが含まれています:
"dateTime":睡眠ステージの測定の日時("YYYY-MM-DDTHH:MM:SS.sss"形式)。
"level":睡眠ステージのレベル("wake"、"light"、"deep"、または"rem")。
"seconds":特定の睡眠ステージで過ごした秒数。
jsonファイルの中身の構造を丁寧に教えてもらえました。記録データには、睡眠タイプが2種類あり、一つは「通常の睡眠」ともう一つは「昼寝等の短い睡眠」で、mainSleepというBool値で前者はTrue、後者はFalseで区別できることが分かりました。また、前者の通常の睡眠には異なる睡眠ステージ(深い睡眠:deep、覚醒:wake、軽い睡眠:light、レム睡眠:rem)、後者の昼寝等の睡眠にはrestless、awake、asleepのステージがあることが分かりました。
jsonファイルの構造が理解できたので、次にそのjsonファイルから必要な情報のみを可読性の良いcsvファイルに出力するPythonプログラムを生成AIに作ってもらいました。ChatGPT、bing、Bardの三者に確認しましたが、Bardが一番賢い回答を返してくれました。以下、そのプロンプトです。
以下のjsonファイルからcsvファイルを作成するPythonプログラムを作成してください。
csvファイルに出力する項目と順番は以下の通りです。
dateOfSleep, startTime, endTime, duration, minutesToFallAsleep, minutesAsleep,minutesAwake, minutesAfterWakeup,timeInBed, efficiencyに続いて、levelsのsummaryについては、以下のルールで分けて、項目名を作成してください。
ルール:
deepをdeep_count, deep_minutes, deep_thirtyDayAvgMinutesの3項目、
wakeをwake_count, wake_minutes, wake_thirtyDayAvgMinutesの3項目、
lightをlight_count, light_minutes, light_thirtyDayAvgMinutesの3項目、
remをrem_count, rem_minutes, rem_thirtyDayAvgMinutesの3項目、
restlessをrestless_count, restless_minutesの2項目、
awakeをawake_count, awake_minutesの2項目、
asleepをasleep_count, asleep_minutesの2項目
jsonファイル:
前述のjsonファイルをコピー
Bardの回答の一部を修正したプログラムは以下の通りです。修正箇所は
① 11〜36行目のwriter.writerowの項目名の追加・削除
② 54〜62行目のfor文内に睡眠のタイプを分けるif〜else文を追加
です。ほぼ完璧なコードでした!
import csv
import json
def create_csv(json_file, csv_file):
with open(json_file, "r") as f:
data = json.load(f)
with open(csv_file, "w", newline="") as f:
writer = csv.writer(f)
# ヘッダー行を作成
writer.writerow([
"dateOfSleep",
"startTime",
"endTime",
"duration",
"minutesToFallAsleep",
"minutesAsleep",
"minutesAwake",
"minutesAfterWakeup",
"timeInBed",
"efficiency",
"deep_count",
"deep_minutes",
"wake_count",
"wake_minutes",
"light_count",
"light_minutes",
"rem_count",
"rem_minutes",
"restless_count",
"restless_minutes",
"awake_count",
"awake_minutes",
"asleep_count",
"asleep_minutes"
])
for entry in data:
# 各項目をcsv行に変換
row = []
row.append(entry["dateOfSleep"])
row.append(entry["startTime"])
row.append(entry["endTime"])
row.append(entry["duration"])
row.append(entry["minutesToFallAsleep"])
row.append(entry["minutesAsleep"])
row.append(entry["minutesAwake"])
row.append(entry["minutesAfterWakeup"])
row.append(entry["timeInBed"])
row.append(entry["efficiency"])
# levelsのsummaryから項目を取得
for level_name, level_data in entry["levels"]["summary"].items():
if(entry["mainSleep"]):
row.append(level_data["count"])
row.append(level_data["minutes"])
else:
if(level_name =='restless'):
for i in range(8):
row.append('')
row.append(level_data["count"])
row.append(level_data["minutes"])
writer.writerow(row)
if __name__ == "__main__":
json_file = "sleep-2023-07-01.json"
csv_file = "sleep-2023-07-01.csv"
create_csv(json_file, csv_file)
jsonファイルの構造の解読からcsvファイルへの出力まで生成AIを使って、労力なく処理することができました。データの前処理も終わりましたので、次回は、本丸のデータ分析を行いたいと思います。