t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

Python matplotlib で朝昼晩の食事カロリーをグラフ表示

今回も摂取カロリー記録システム開発の続き。
表示部分をmatplotlibというPythonのグラフライブラリを使って作っていく。

動作イメージ

実際の動作イメージはこんな感じ。
f:id:t-hom:20210220165014p:plain

積み上げ棒グラフで、下段から朝食、昼食、夕食の順にカロリーを表示させる。
斜線が入った薄い緑色のボックスはカロリー摂取目標を示していて、この範囲に届かないと基礎代謝を下回る無理なダイエット、この範囲を超えると食べすぎで痩せない。

今入れているデータは適当に設定したので実際のデータを使って表示させるのはもう少し先になる見通しである。

コード

import numpy as np
import matplotlib.pyplot as plt
 
record_date = np.array(["Feb.8", "Feb.9", "Feb.10", "Feb.11", "Feb.12", "Feb.13", "Feb.14"])
minimum = np.array([1600, 1600, 1600, 1600, 1600, 1600, 1600])
breakfast = np.array([400, 600, 700, 350, 700, 400, 450])
lunch = np.array([1000, 750, 1000, 1300, 600, 500, 350])
dinner = np.array([980, 800, 500, 500, 800, 800, 0])
maximum = np.array([2400, 2400, 2400, 2400, 2400, 2400, 2400])
 
plt.title("Calorie Record", fontsize = 22)
plt.xlabel("Date", fontsize = 22)
plt.ylabel("Calorie", fontsize = 22)
plt.grid(True)
 

plt.bar(record_date, maximum-minimum, width=0.25, bottom = minimum, tick_label = record_date, align="center", label="Guideline", color = "#98fb98", edgecolor="#008000", lw=0, hatch="/////")

plt.bar(record_date, breakfast, width=0.2, tick_label = record_date, align="center", label="Breakfast", color = "#f3d394")
plt.bar(record_date, lunch, width=0.2, bottom = breakfast, tick_label = record_date, align="center", label="Lunch", color = "#45938b")
plt.bar(record_date, dinner, width=0.2, bottom = breakfast+lunch, tick_label = record_date, align="center", label="Dinner", color = "#003a34")

plt.show()

分岐も繰り返しも使ってない為、全くインデントが無くてあんまりpythonらしくないコードになってしまった。

積み上げ棒グラフって面倒なイメージがあったけど、他のサイトを参考にコードをコピペしていじってるうちにさくっとできたので、matplotlibの強力さを改めて実感した。


今回のポイントは以下の部分。

plt.bar(record_date, maximum-minimum, width=0.25, bottom = minimum, tick_label = record_date, align="center", label="Guideline", color = "#98fb98", edgecolor="#008000", lw=0, hatch="/////")

plt.bar(record_date, breakfast, width=0.2, tick_label = record_date, align="center", label="Breakfast", color = "#f3d394")
plt.bar(record_date, lunch, width=0.2, bottom = breakfast, tick_label = record_date, align="center", label="Lunch", color = "#45938b")
plt.bar(record_date, dinner, width=0.2, bottom = breakfast+lunch, tick_label = record_date, align="center", label="Dinner", color = "#003a34")

上から順に、カロリー摂取目標、朝食、昼食、夕食をプロットしている。
ここでは積み上げグラフ機能を使っているわけではなく(そもそもあるのか知らない。たぶんない。)、単に普通の棒グラフの機能で、bottomを指定することで積み上げグラフを作っている。

だからdinnerのbottomはbreakfastとlunchを足した値となっていて、そこからdinner値分のグラフを描いているのだ。

一見面倒に思えるこのような指定は、カロリー摂取目安を描画するのに非常に役に立った。
つまり、bottomが自由に指定できるため、他の値に影響を受けずに任意の位置からデータを描画できるのだ。

今回は基礎代謝をminimumに、痩せるための最大摂取カロリー目安をmaximumに指定しているため、bottomがminimum、値はmaximum-minimum、Widthは他のグラフより少し太い0.25にすることでかぶさっても見えるようにした。

このあとの課題

グラフ表示の目安が付いたので、あとはこれに適したデータを準備してやる必要がある。
M5スタックから入力したカロリーデータは時刻・カロリーが1品1レコードの形式でcsv保存されている。
これを特定時刻を基準にして朝食・昼食・夕食の3種類に分類し、日付ごとのデータに分類しなければならない。
またしばらくpandasと格闘することになりそうだ。

あと、直近の体重データの最軽量値からカロリー摂取目安を計算するプログラムも必要になる。

それができれば、あとは体重変動グラフと摂取カロリーグラフを、どんなときに切り替えるかという課題もある。
体重を量った直後は体重グラフ、カロリー記録直後はカロリーグラフでいいんだけど、それ以外の待機時間にどっちも意識させたいのでボタンなどのUIでの任意切替かタイマー切替にしたい。

以上

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。