termgraph を自分のスクリプトから使いたい

ターミナルに簡単にグラフを書きたいと思って PyPI を探してみたら termgraph というのを見つけたものの、README.md を見ると何やらコマンドとして使うのが想定されているようで Python スクリプトから呼び出す方法については書かれていなかった。 仕方ないので termgraph の中を見てみて、こんな感じでやれば自分の Python スクリプトから termgraph 内の関数を呼び出してグラフを書けるよ、という内容のメモ。

termgraph に付属のサンプルデータにある data/ex4.txt を例にする。

# Example Data Set 4 with 2 Categories
@ Boys,Girls
2007,183.32,190.52
2008,231.23,5.0
2009,16.43,53.1
2010,50.21,7
2011,508.97,10.45
2012,212.05,20.2
2014,30.0,20.0
  • 2007 年から 2014 年までの、Boys と Girls についてのなんらかの値が入っている。
  • # で始まる行はコメント
  • @ で始まる行は、データ行の列名だと思っておけば良い。termgraph の中では categories と呼ばれている
  • 以降の行は、label,boys,girls という並びでカンマ区切りでデータが置かれている

お手本

termgraph コマンドを使うと、こんなグラフが書ける。

% termgraph ~/src-misc/termgraph/data/ex4.dat 

▇ Boys  ▇ Girls  


2007: ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 183.32
      ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 190.52
2008: ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 231.23
      ▏ 5.00 
2009: ▇ 16.43
      ▇▇▇▇▇ 53.10
2010: ▇▇▇▇ 50.21
      ▏ 7.00 
2011: ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 508.97
      ▇ 10.45
2012: ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 212.05
      ▇ 20.20
2014: ▇▇ 30.00
      ▇ 20.00

% 

コマンドを使うのではなく、自分の Python スクリプトから termgraph の中のものを使って同じことをやろう、というのが目標。

概要

データを用意して、以下の termgraph 内の関数を呼び出す。

  • termgraph.check_data
  • termgraph.print_categories
  • termgraph.chart

termgraph.chart 関数

最終的に termgraph.chart 関数を呼んでグラフを書くことになる。

def chart(colors: List, data: List, args: Dict, labels: List) -> None:
    """Handle the normalization of data and the printing of the graph."""

colors, data, args, labels を用意する必要がある。

  • colors - チャートの色の list
  • data - チャートのデータの list
  • args - termgraph.chart 関数のオプションを指定する dict
  • labels - 各要素の名前

colors リスト

上の例では Boys / Girls ともに端末の文字の色でグラフが描かれるが、termgraph コマンドに --color {blue,red} とオプションを付け加えると、Boys は青で Girls は赤でグラフが描かれる。

この colors リストは自分で用意する必要はない。termgraph.check_data 関数の返り値を colors にする。

colors = tg.check_data(labels, data, args)

では、どのように色を指定するのかというと、args['color'] に値を入れておく。端末の文字色でよければ None を入れる。categories の要素ごとに色を変えたい場合リストに色を指定する、例えば Boys は青で Girls は赤にしたいという場合には、args['color'] = ['blue', 'red'] という感じ。このリストの要素数は、categories リストの要素数と等しくなくてはならない。

指定できる色は、termgraph.AVAILABLE_COLORS に定義されている。

# ANSI escape SGR Parameters color codes
AVAILABLE_COLORS = {
    "red": 91,
    "blue": 94,
    "green": 92,
    "magenta": 95,
    "yellow": 93,
    "black": 90,
    "cyan": 96,
}

色を追加で定義したいのなら、この AVAILABLE_CHARTS に追加すれば良い。例えば白なら tg.AVAILABLE_COLORS = {'white': 97} と書く。 wikipediaANSI escape code のページを見ると、30 から 37 の値も使えそうではあるが試してはいない。

labels リスト

2007 から 2014 までの文字列のリストを作っておけば良い。

labels = ['2007', '2008', '2009', '2010', '2011', '2022', '2014']

data リスト

[boysの値,girlsの値] のリストを作っておけば良い。こんな感じ。

data = [
    # Boys,  Girls
    [183.32, 190.52],
    [231.23,   5.0 ],
    [ 16.43,  53.1],
    [ 50.21,   7  ],
    [508.97,  10.45],
    [212.05,  20.2 ],
    [ 30.0,   20.0 ],
]

args dict

termgraph コマンドのヘルプ (termgraph --help) を参考に dict を作っていけば良いのだが、termgraph.chart 関数や termgraph.check_data 関数を呼ぶだけなら不要だったりするものや、そもそも使われていないものもある。。。

termgraph.chart を呼ぶために必須なもの

オプション名 タイプ オプションの意味
width int グラフの幅。デフォルト 50。
format str 各棒の後に数値を表示する際の形式。デフォルト {:<5.2f}
suffix str 各棒の後に表示した数値の後につける文字列。 % とかをつけたいなら。 
no_labels bool 各棒の先頭にラベルを表示するかどうか。
no_values bool 各棒の後に値を表示するかどうか。
color list 色名をリストで指定。 ["blue", "red"] とか。指定がなければ None を入れておけば良い。
vertical bool 横ではなく縦にグラフを書きたい!
stacked bool 各カテゴリを合わせたグラフにしたい!
histogram bool ヒストグラムでお願い!
bins int ヒストグラムにしたときの bin の数。 デフォルト 5。
different_scale bool Categories have different scales らしいが調べてない

termgraph コマンドのオプションとして定義されているが、chart や check_data を使うにあたっては不要なもの

  • title
  • calendar
  • start-dt
  • custom-tick
  • delim

タイトルは自分で書けばいい。

calendar と start-dt は、カレンダーヒートマップを書きたい場合に使う。termgraph.chart 関数ではなく、termgraph.calendar_heatmap 関数を呼ぶ。

custom-tick は、グラフを描くときの文字を変更したい場合に使う。

delim は、データ入力をファイルから行うときに区切りもじを指定するために使う。(termgraph.DELIM の値を変える。)

termgraph コマンドのオプションとして定義されているが使われていないもの...

  • space-between
  • label-before

というわけで、こんな感じで args を用意すればよい。

args = {
    'width': 50,
    'format': '{:<5.2f}',
    'suffix': '',
    'no_labels': False,
    'no_values': False,
    'color': None,
    'vertical': False,
    'stacked': False,
    'histogram': False,
    'bins': 5,
    'different_scale': False
}

categories リスト

凡例を表示するには、termgraph.print_categories(categories, colors) を呼ぶ。 categories リストは ['Boys', 'Girls'] として用意する。

組み合わせてみる

全部合わせてみると、こんな感じのスクリプトになる。

from termgraph import termgraph as tg

# data/ex4.dat
categories = ['Boys', 'Girls']
labels = ['2007', '2008', '2009', '2010', '2011', '2022', '2014']
data = [
    # Boys,  Girls
    [183.32, 190.52],
    [231.23,   5.0 ],
    [ 16.43,  53.1],
    [ 50.21,   7  ],
    [508.97,  10.45],
    [212.05,  20.2 ],
    [ 30.0,   20.0 ],
]
args = {
    'width': 50,
    'format': '{:<5.2f}',
    'suffix': '',
    'no_labels': False,
    'no_values': False,
    'color': None,
    'vertical': False,
    'stacked': False,
    'histogram': False,
    'bins': 5,
    'different_scale': False
}

colors = tg.check_data(labels, data, args)
if categories:
    tg.print_categories(categories, colors)
tg.chart(colors, data, args, labels)

hoge.py として保存して、実行してみる。

% python hoge.py
▇ Boys  ▇ Girls  


2007: ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 183.32
      ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 190.52
2008: ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 231.23
      ▏ 5.00 
2009: ▇ 16.43
      ▇▇▇▇▇ 53.10
2010: ▇▇▇▇ 50.21
      ▏ 7.00 
2011: ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 508.97
      ▇ 10.45
2022: ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 212.05
      ▇ 20.20
2014: ▇▇ 30.00
      ▇ 20.00

% 

できあがり。