予算消化率の水平ゲージをledger-cliとgnuplotで描く

きっかけ

新型コロナウイルス が、政府のunbelievableな不手際もあって急速に蔓延してます。ニュースを見るたびに気が滅入ってきます。そこで、というわけでもありませんが、一ヶ月の 支出予算 がどれくらい消化されているかを表示する 水平ゲージ (horizontal linear gauge)を作ってみました。ねらいは次のようなものです:

(例えば)2月1日から2月20日までの累積支出額が、月額支出予算の何パーセントに当たるのかを可視化したい

予算消化率の可視化については前回の投稿で、GNOME端末での プログレッシブ・バーグラフ を紹介しました。今回はそれよりももう少しグラッフィックに図1のような水平ゲージを描きます。

図1:  当日までの予算消化率をプロットする水平ゲージ

図1: 当日までの予算消化率をプロットする水平ゲージ

仕掛け

当月内の当日までに支出した金額の累計はleger-cliで算出します。それを分子にし今月の支出予算を分母にしてパーセンテージを計算します。その値をgnuplotにスクリプト内変数として引き渡して、水平ゲージ内に 太めの黒い線 を描くというシンプルな仕掛けです。

ネットには見当たらない?

当初、gnuplotによる水平ゲージ表示例をネット上で探してみましたが、探し方が悪いのか見当たりませんでした。水平ゲージだけでなく、図2のような 計器盤 風のゲージ(出典)もgnuplotで描いた例を見つけることができませんでした。

図2:  計器盤風ゲージチャートの例

図2: 計器盤風ゲージチャートの例

こうしたゲージ類は、今流行りのいわゆる ダッシュボード では多用されていますが、 サイエンスの世界 では余り使われませんよね。そのため、Excelなどでは簡単にこうした図を描ける(らしい)し、それ以外にもゲージ類を描くための専用のアプリケーションが ビジネス向け にたくさん存在しています。

それらを使わず、あえてgnuplotで描いてみようと思った理由は:

  • gnuplotはledger-cliと とても相性が良いし使い慣れている
  • Excleはこれまでほとんど真面目に使ったことがない

などです。

前置きはこの辺にして中身を紹介します。

環境

  • ubuntu 16.04
  • GNU bash, バージョン 4.3.48(1)-release (x86_64-pc-linux-gnu)
  • gnuplot 5.2 patchlevel 8

コーディング

次の2つのスクリプトを組み合わせます。

  • bashスクリプト : ledgerを動かして平均値などを計算します。下のgnuplotスクリプトをコールします。
  • gnuplotスクリプトsimple-horizntl-gauge.plt ): 標準的な の積上げ棒グラフ(rowstacked)を描きますが、できた画像をあとで90度回転して にする関係で、目盛りの文字列を90度回転しておきます。

コードは大急ぎで書いたままでブサイクですがとりあえず動いています。スキルの高い人が書けばもっとスマートな方法があると思います。ま、とりあえず、ということで勘弁して下さい。

bashからgnuplotへの変数と文字列の受け渡し

bashスクリプト内のledgerで算出した支出パーセントが格納されている 変数$pct )をgnuplotに percent という変数名で引き渡します。

引き渡す 文字列 は図のタイトル( '% of Monthly Budget' )です。これをgnuplot内の変数 fig_title として引き渡しています。これについては必ずしも両者の間で引き渡ししなくても良いのですが、将来の汎用性のために書いておきました。

そのパートだけを抜き出すと次のようになっています:

gnuplot -e "percent='$pct'; fig_title='% of Monthly Budget'"\
	./simple-horizntl-gauge.plt

bashスクリプト

#!/bin/bash
#
#  毎月の支出予算に対して当日までの支出金額がどれくらいになるかを
#  水平方向のゲージチャートhorizontal bar gauge chart に表示する

###############################################
# 当日までの支出額は支出予算の何%にあたるかを計算
###############################################
budget=`expr 400000 - 40000`  # 360,000円
##
# Ledgerで当日までの累積支出額($month_total)を求める
ledger bal -J ^expenses -p 'this month' --depth 1\
       -X JPY > ./tmp-total.csv
month_total=`cut -d ' ' -f 2 ./tmp-total.csv`
##
# 予算($budget)に対する支出のパーセント($pct)を計算
pct=`echo "scale=3;${month_total} / ${budget} * 100" | bc`
#
##############################################################
# gnuplotで縦方向(普通の)積上げバーグラフを描く
##
gnuplot -e "percent='$pct'; fig_title='% of Monthly Budget'"\
	./simple-horizntl-gauge.plt
###############################################################
# 上で作った積上げバーグラフ(out-sample.png)を90度右回転しrotated-fig.pngに格納
convert -rotate 90 ./out-sample.png  ./rotated-sample.png
##
# 余計な余白をトリミングしてhorizontal-gauge.pngに格納
convert ./rotated-sample.png -trim  ./horizontal-gauge.png
##
# 表示する
mupdf ./horizontal-gauge.png &

gnuplotスクリプト

#
#    gnuplot script for horizontal gauge of % monthly budget
#

$Plotdata <<EOD
1 60 20 20 20
# 積上げ棒グラフ(4段)の値
EOD

reset

set terminal pngcairo font 'Arial, 12'
set style data histogram
set style histogram rowstacked
set style fill transparent solid  0.5 border -1
#
unset xtics
unset ytics
set ytics rotate by 90
set xrange[0:1]
set yrange[0:120]
set y2label fig_title." (`date "+%Y/%m/%d"`)" offset 1.0
set xlabel ' '
#
set size 0.9
set size ratio 5
set boxwidth 2.0
# 予算消化率変数percentはbashスクリプトから引き渡される
##
set arrow 1 from 0,percent to 1,percent nohead lc rgb "black" lw 5
set output "./out-sample.png"
#
plot $Plotdata using 2:xtic(1) notitle linecolor rgb "green",\
	     '' using 3 notitle  linecolor rgb "light-green",\
	     '' using 4 notitle  linecolor rgb "yellow",\
	     '' using 5 notitle  linecolor rgb "red"
set output

使いみち

買い物が終わった後、レシートなどを見ながらその日の支出をledgerで転記しますが、転記が終わったら、金額などの確認のためにいくつかのスクリプトを起動させて、各種のグラフやチャートを表示させます。そのスクリプト群の一つに、この水平ゲージ表示スクリプトを埋め込んでいます。

ゲージスクリプトが起動すると、スクリーンの 空いた 場所にこのゲージが表示されます。表示されている情報価は大したものではないのですが、見た目がもっともらしいので(笑)満足しています。

Acknowledgement

次のサイトがとても参考になりました。