[Python][データの見えざる手] OuraRingからmetsを取得しU分布に従うのか調べてみた

# 概要
[データの見えざる手](https://amzn.to/3qxSZYk)によれば、人間の身体活動はある規則に従って分配される

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1023362/40e1a285-a106-2fb8-7e18-99e2ea8ad05a.png)
> 出典 [データの見えざる手](https://amzn.to/3qxSZYk)

このグラフは

* 手首にリストバンド型加速度センサを付けて、身体運動の回数(N回/分)を測定する
* 一定期間中の、身体運動の回数の、出現頻度累積確率を縦軸に取る(対数目盛)

ことで、描ける
ここから、分かることは

* 60回/分の活動は一日の半分を占める(占めることになる)
* 60~120回/分の活動は一日の1/4を占める(占めることになる)

例えば、ある仕事が60~120回/分の運動量だとすれば、
その仕事は一日の間で1/4分の時間しか費やせない(それ以上の時間、その仕事は頑張れない)
という事

なるほど、面白いと思って、これと似たことを[OuraRing](https://amzn.to/3u6NXV2)でやってみた

# OuraRingからMetsを取得する
[データの見えざる手](https://amzn.to/3qxSZYk)では、加速度センサによる動きを使っていた
自分の所有しているOuraRingではMetsという値が取れているため、これで代用する
[OuraRing](https://amzn.to/3u6NXV2)のAPIを使って、Metsを取得する

OuraAPIの使い方は[この記事](https://note.com/mxiskw/n/naca60e24e0d1#OJxhE)が参考になる

```sample.py
import requests
import json
import os
import datetime
import collections
import pprint

BASE_URL = "https://api.ouraring.com/v1/"
TOKEN    = "access_token=" + str(os.environ.get("OURA_TOKEN"))

def create_date_str(weeks_offset=0):
    today = datetime.datetime.today()
    target_date = today - datetime.timedelta(days=1,
                                             weeks=weeks_offset)
    return target_date.strftime("%Y-%m-%d")

def create_url(weeks_offset=0):
    end_date = create_date_str(weeks_offset)
    start_date = create_date_str(weeks_offset+1)
    url = f"{BASE_URL}activity?start={start_date}&end={end_date}&{TOKEN}"
    return url

if __name__ == "__main__":
    headers = {"content-type": "application/json"}
    mets_counter = collections.Counter()
    
    for week_offset in range(5):
        responce = requests.get(create_url(week_offset), headers=headers)
        data = responce.json()
        for activity in data["activity"]:
            mets_counter.update(activity["met_1min"])

    total_num = sum(mets_counter.values())
    for mets,count in mets_counter.items():
        mets_counter[mets] = count/total_num

    with open("mets.txt","w") as f:
        for mets,probability in mets_counter.items():
            f.write(f"{mets}\t{probability}\n")
```
> https://github.com/box16/OURA_API

metsを取得するためのurlは
`https://api.ouraring.com/v1/activity?start=YYYY-MM-DD&end=YYYY-MM-DD&access_token=TOKEN`

`create_date_str`,`create_url`で一週間ごとのactivityデータを取得するURLを生成する
一週間分毎に{mets : 出現回数}を更新する
(結構データ量大きそうだからメモリ節約のため、必要な分だけ細かく取得しているつもり)

これを、何かしら出力する

# データの可視化
まず、単純に`mets - 出現確率`を可視化する

![出現確率と mets (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1023362/9c01a76c-9f60-ee84-9833-cce5641547e3.png)

2mets以下の出現頻度が高い事が分かる

次に`mets - 累積確率`を可視化する
(累積確率は、あるmetsと、それ以前すべてのmetsの出現確率の和→総和が1)
![累積確率 と mets.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1023362/8b28ceeb-dade-9afd-fa0d-51d1c4a64ba0.png)

2mets以下で一日の80%を占めている
2mets以上は20%

この時点でmetsもU分布に従いそうなことが分かった

これを
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1023362/40e1a285-a106-2fb8-7e18-99e2ea8ad05a.png)
> 出典 [データの見えざる手](https://amzn.to/3qxSZYk)

この画像っぽく見せてみる
`mets - (1-累積確率)`の縦軸を対数目盛にすると出来た
![累積確率 と mets (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1023362/fe3d395d-0767-19f3-7a63-419537755eb2.png)

# Metsと実際の運動の紐づき
https://www.nibiohn.go.jp/eiken/programs/pdf/mets_n.pdf

例えば、

* 立ちながらの読書 : 1.8mets
* リクライニングでの読書 : 1mets
* 座位作業(読書含む) : 1.5mets

とある
[データの見えざる手](https://amzn.to/3qxSZYk)を参考に、読書の[カルノー効率](https://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%AB%E3%83%8E%E3%83%BC%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB)を計ると
1 - 1/1.8 = 0.44
最大、1日の44%(活動時間16時間として7時間くらい)までしか読書できない
(metsで言えばの話だから、読書に限らず1~1.8mets程度の活動は1日7時間しか出来ない)
と言えそう

筋トレは

* ウェイトリフティング : 6mets
* 一般的な健康教室での運動 : 5.5mets 

で

1 - 5.5/6 = 0.083
1日の8%程度(1時間程度)が限界

# まとめ
* [データの見えざる手](https://amzn.to/3qxSZYk)マジおもしれぇ
* MetsもU分布に従っていた
* Mets表とOuraRingのトラッキングがあれば、効果的に一日のスケジューリングが出来る