たくさん寝太郎の寝床

料理とITと皿回しが好きなオタクのブログ

日付間隔を考慮したグラフ描画の話

こんにちは、たくさん寝太郎です。

在宅が増えたせいか夏頃から急激に体重が増え始め、遂に70kgの大台に乗ってしまったのでダイエットを始めることを決意しました。
ちなみに院試の時の体重が60kgくらいだったので入院して10kgくらい太ったことになります。





まずは体重管理をするところから始めました。
家にある体組成計にスマホ連動機能が付いてなかったので、「自分で数値をメモする→excelなどで管理する」という方法を取っていました。

f:id:kaworu_mk6:20201025021732p:plain:w200

メモは上から(日付、体重、体脂肪率、筋肉量、内臓脂肪レベル、基礎代謝、体内年齢)になっています。
これをnumbersに入力して、下図のようにグラフ表示していました。

f:id:kaworu_mk6:20201025021856p:plain


しかし、この方法だと色々問題点があります。

  • 体組成計の数値をメモ→numbersに打ち込むという作業が面倒臭い
  • グラフの日付の間隔が一定となっている


通常体重管理では毎日同じ時間に測ることが大事とされているのですが、寝太郎の生活リズムは崩壊しているので毎日測定するのは非常に難しいです。上記のnumbersのグラフは測定間隔が一定ではないのに日付の間隔が一定となっています。


「体重管理アプリ使えや...」で終わる話ですが、何となく自分でアプリを作ってみたくなったのでまずは上記2点の問題点を解決するプログラムを書きました。

新しいデータをコピペで追加する

dietディレクトリを作り、body_comp.csvというファイルを作っておきます。
headerは以下のようにしておきます。

date,weight,BFR,muscle_mass,visceral_fat,metaborism,body_age


プログラムは次のようになりました。

import os
import csv

path = '~/diet/body_comp.csv'
path = os.path.expanduser(path)

def add_new_data(path):
    new_data = input('please copy & paste new data: ')
    new_data = [float(n) for n in new_data.split(' ')]
    new_data[0] = int(new_data[0])

    with open(path, 'a') as f:
         writer = csv.writer(f, delimiter=',')
         writer.writerow(new_data)


体組成を計測し、メモ帳に「1026 70.00 20.0 50.00 8.0 1500 25」のようにメモしておきます。
上記プログラムを実行し、メモ帳からコピペするとbody_comp.csvに自動で新しいデータが入力されるようになりました。

データをプロットする

プログラムは以下の通りです

import pandas as pd
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib.dates import date2num, DateFormatter

path = '~/diet/body_comp.csv'
path = os.path.expanduser(path)

def plot_data(year):
    df = pd.read_csv(path)
    date = [(int(d/100), d%100) for d in df['date']]
    
    fig = plt.figure(1)
    ax = fig.add_subplot(111)
    xax = ax.xaxis
    new_xticks = date2num([datetime(year, d[0], d[1]) for d in date])
    xax.set_major_locator(ticker.FixedLocator(new_xticks))
    xax.set_major_formatter(DateFormatter('%m-%d'))
    ax.plot(date2num([datetime(year, d[0], d[1]) for d in date]), df['weight'], 'o-')
    ax.set_ylim(62.0, 70.0)
    ax.tick_params(axis='x', rotation=270)
    plt.grid(b=True, which='major', axis='y', color='lightgrey', linestyle='-')
    plt.savefig('weight_transition.png')


最初は日付を日数変換してプロットした後にx軸を日付表示するということを考えていたのですが、色々調べているうちにmatplotlibにdatetimeを扱う機能があることを知りました。

これを使って1ヶ月分のデータをプロットした結果が下図のようになります。
f:id:kaworu_mk6:20201025025209p:plain

日付の間隔を考慮してプロットすることが出来ました。

今後の課題

  • 測定時間も考慮する
  • メモしてからプログラム立ち上げてコピペが面倒臭い→アプリ化して過程を減らす

おわり