1byone 体組成計のCSVデータから体重変化チャートをプロットする

ここでは

1byone 体組成計からエクスポートされたCSVデータを
bashシェルスクリプトとgnuplotを使って折れ線グラフにする方法を紹介します

1byone 体組成計から CSVデータを取得する方法 については CSVデータをエクスポートできる家庭用体組成計 – 1byone smart scale をごらんください。

サンプル出力

図1: 過去3か月間の1日ごとの体重変化と7日間の移動平均チャート

図1: 過去3か月間の1日ごとの体重変化と7日間の移動平均チャート

このようなチャートを描くためのスクリプト taiju_plotter.sh のダイアグラムを巻末の参考資料に掲載しました。

ダイアグラムで背景が 薄く黄色 に着色された5つのブロックについて、以下に説明します。

解説

1. BFSデータファイル選択

BFSBody Fat Scale の略です。
~/ダウンロード/ ディレクトリ内から文字列 BodyFatScale を含むファイルを最新順に表示し、そのリスト内から一つを選択します。
空のエンター (デフォルト)が入力されたら、一番上=最新のファイルを選択、それ以外のファイルを選択するときには、リスト中から コピー して入力プロンプトに ペースト します。

#
#  処理対象とするBodyFatScale データファイルを取得する
#  (BodyFatScaleファイルをfind検索・表示・入力する)
hit_list=$(find ~/ダウンロード/ -name 'BodyFatScale*.csv' -print0\
	       | xargs -0 ls -at\
	       | cut -d'/' -f 4- )

echo -e "** 候補ファイル(最新順) \n${hit_list}"
echo -e "\nエンターで最新ファイルを選択, それ以外ならコピペして下に貼り付ける"
read -r -p "Which BodyFatScale date file?  " which

# エンターかコピペファイ名取得かを選択する
if [ -z "${which}" ]; then
    bodyfatscale_path=$(echo "${hit_list}" | head -1 )
else
    bodyfatscale_path=$(echo "${which}")
fi
#
bfs_fname=${bodyfatscale_path}
echo -e "\n処理対象の BodyFatScale file= ~/${bfs_fname}"

2. 分析対象とする期間(period)を入力

体重プロットのX軸(期間)を、1週、1か月、3か月、6か月、1年、2年の中から一つ選択します。デフォルトは1か月。

#  Period 入力プロンプト
if [[ $# == 0 ]]; then
    read -r -p 'Range?  [w]eek, [m]onth, [3] months, [6] months, [y]ear, or [2y]ear/[24m[onths] : '  keyin
    if [[ -z $keyin ]]; then
	keyin="m" # default goes to month
    fi
else
    keyin=$1
fi

3. 体重推移データファイルの作成・保存

データの日付、時間を絞り込むために dateutils.dgrep を使っています。ubuntuで dateutils.dgrep を使うには dateutils パッケージのインストールが必要です。

#
# 体重推移データファイルを作り保存する
#
# ヘッダー行を削除し、日時と体重を抽出してtmp-date-taiju.csv生成(全期間)
sed -e '1d' ~/"${bfs_fname}"\
    |cut -d',' -f1,2\
     > ${tmp_dir}/tmp-date-taiju.csv

#  tmp-date-taiju.csvから午前のデータ( <12:00:00 行)を抽出し
#  tmp-AM-date-taiju.csv に格納
dateutils.dgrep "<=12:00:00"\
		< ${tmp_dir}/tmp-date-taiju.csv\
		> ${tmp_dir}/tmp-AM-date-taiju.csv

# 上のAMデータからperiod の指定日from_dateよりも新しい日付を含む行をgrep抽出
from_date=$(date -d "${period} ago"  '+%Y-%m-%d')
dateutils.dgrep ">=${from_date}"\
		< ${tmp_dir}/tmp-AM-date-taiju.csv\
		> ${tmp_dir}/tmp-in-period.csv

4. 移動平均データファイルの作成・保存

このパートでは、MA(moving average;移動平均)のデータファイルを作成します。

  • 移動平均を計算するために自前の関数( moving-average.sh )を使っています。この関数のソースコードは「ローソク足と移動平均をgnuplotで描く」の記事中の「参考資料」節をご覧ください。
#  MA(移動平均)計算用の補助データファイルを生成
#   日にちに余裕をもたせてwindows_size+5にする
aux_days=$(( window_size + 5 ))
aux_period_date=$(date '+%Y-%m-%d' -d "${from_date} - ${aux_days} days" )

dateutils.dgrep ">${aux_period_date}"\
		< ${tmp_dir}/tmp-AM-date-taiju.csv\
		> ${tmp_dir}/tmp-aux-period.csv

#  csvファイルをsortし、時刻とカンマを削除
target_file_arr=(
    "${tmp_dir}/tmp-aux-period.csv"
    "${tmp_dir}/tmp-in-period.csv")

for file in "${target_file_arr[@]}"; do
    # 日付の古いものから昇順にsort
    sort -u ${file} -o ${file}
    # 時刻部分とその後ろのカンマを削除する
    sed -E -i  's/[0-9]{2}:[0-9]{2}:[0-9]{2},//g' ${file}
done

#  tmp-aux-period.csv について移動平均を計算する
#  移動平均関数をコール: 引数1=データファイル名, 引数2=列の位置, 引数3=窓サイズ
#                        出力は ./tmp-MA-out.dat
moving-average "${tmp_dir}/tmp-aux-period.csv" 2 7

#  date-taiju-MA生成(date-taiju.csv に tmp-MA-out.dat をjoin)
join -a 1 ${tmp_dir}/tmp-in-period.csv ${tmp_dir}/tmp-MA-out.dat\
     > ${tmp_dir}/date-taiju-MA.dat

5. Gnuplotで描出

Gnuplotのスクリプトはシェルスクリプト内の ヒアドキュメント にしています。

  • gnuplotで使用する変数($xrange1, $xrange3, $title_from_date, $title_to_date, $out_file, $data_to_plotなど)の値は、このヒアドキュメントの前に定義しています。
gnuplot <<EOF
  set terminal pdfcairo transparent enhanced font 'Arial, 12'
  set datafile separator " "

  # 図のタイトル/STATS
  set title "体重推移と移動平均(${title_from_date} - ${title_to_date})" font 'Arial, 14'
  stats "${tmp_dir}/date-taiju-MA.dat" using 1:2 nooutput

  # yrange の最大最小を取得する
  ymax=ceil((STATS_max_y + 0.1) *10) /10.0
  ymin=floor((STATS_min_y -0.1) *10) /10.0

  # X軸設定
  set xdata time
  set timefmt "%Y-%m-%d"
  set format x "%01m/%01d"
  set xrange ["${xrange1}":"${xrange3}"]

  # Y軸設定
  set ylabel "体重(kg)" font 'Arial,14'
  set yrange [ymin:ymax]
  set y2range [ymin:ymax]
  set format y  "%3.1f"
  set format y2 "%3.1f"
  set y2tics
  set grid ytics

  set output "${out_file}"
  plot "${data_to_plot}"\
	 u 1:2 w linespoint title "体重(kg)" lc rgb "blue"\
		lt 7 ps 0.3 lw 1.0,\
      '' u 1:3 w linespoint title "移動平均(7日)" lc rgb "#FF7D7D"\
		ps 0.3 lw 3.5
  set output
EOF

まとめ

作成した体重推移の折れ線グラフをAndroidタブレットのJoplinで見えるようにするために、PDFをSVGに変換し、Dropbox内の Joplin/pics/ ディレクトリに保存しています(ダイアグラムの最後のブロック=「後始末」)。

体重以外の体組成データも、これと同じ方法で可視化できますが、今のところはこれで満足しています 😄

参考資料

シェルスクリプトtaiju_plotter.sh のダイアグラム

背景が薄黄色のブロックについて本文中で解説しました1

図1: taiju_plotter.sh のダイアグラム

図1: taiju_plotter.sh のダイアグラム


  1. このダイアグラムはMermaid を使って書きました。 ↩︎