百日半狂乱

Shut the fuck up and write some code!!

Linuxターミナル、コマンドtips その5: gnuplotの基本的な使い方と勉強会を開く時に期待してはいけないこと

(2019/06/29追記) 実践的、網羅的かつ簡潔にまとまったドキュメントを見つけたのでメモ(日本語訳*1

github.com

このtipsはこれからLinuxを使っていく必要がある人、特に端末操作に苦戦している人、もしくは端末操作に対して嫌悪感すら抱いている人に向けて書いたものです.作成の経緯はその1の冒頭および注釈に書きました.

今回は、Linuxターミナル、コマンドtipsと銘打ってますが、言うほど一般的な話題ではないです.gnuplotに興味が無ければ前回のシェルスクリプトの活用例としてどうぞ.

前回の話題

シェルスクリプトのハマリ所とデバッグ手法

Linuxターミナル、コマンドtips その4: シェルスクリプトのハマリ所とデバッグ手法

今回の話題

gnuplotの基本的な使い方*2

gnuplotの基本的な使い方

シンプルなgnuplotから始まり、複雑なグラフを描けるようにしていく

また、使い回せるようにシェルスクリプトとしての工夫を少しだけやる

最低限必要そうな設定だけを行ったgnuplot

最初からヒアドキュメントを使ってシェルスクリプトにしているので、そのまま使用可能

まずは以下のプロットデータをグラフ化してみる

プロットデータを記録しているファイル内で#で始まる行はコメント扱い

X/Yのデータのデリミタはデフォルトでスペース

#X Y
1 10
2 20
3 30
4 40

上記のプロットデータをsample1.plotというファイル名で用意した上で以下のスクリプトを実行すると、以下のsample1.pngが生成される

#!/bin/bash

# ヒアドキュメント(<<- EOFから始まってEOFで終わるコード)を使ってgnuplot用のスクリプトを直接gnuplotに実行してもらう
gnuplot <<- EOF
#Y軸のグリッド線を入れる
set grid y

#凡例の位置(center, left, right, outside, top, bottom等)
set key center top

#xy軸のラベル設定
set xlabel "hoge"
set ylabel "fuga"
#図のタイトル、論文やスライドのグラフには原則不要、進捗報告用とかに
set title "title hogefuga"

#png画像を作る場合
set terminal png
#出力先のファイル指定(相対パス)
set output "./sample1.png"

# プロットデータからグラフ生成
# 基本:plot "filename" with 描画スタイル オプション
# withの後に続く描画スタイルの指定(必須)でグラフの種類が決まる
# with lp(linespoints)
# title:凡例名
plot "./sample1.plot" with lp title "foobar"
EOF

生成されたsample1.png

f:id:doi-t:20150330230000p:plain

もう少し色々やったgnuplot

1つのプロットファイルに複数のデータを書いておき、それらを1つのグラフにまとめて出力できる

例えば, 以下のような形のプロットデータがあるとする

#x y1  y2  y3
20 100 150 700
30 300 150 200
40 900 150 400

上記プロットデータを保存したsample2.plotというファイルを用意した上で以下のスクリプトを実行すると、sample2.pngというグラフが生成される

ここでは、フォントサイズ、画像サイズ、値の範囲、グラフの点や色のカスタマイズなど、見栄えの問題でやりたいことをひと通りやってみた

#!/bin/bash

gnuplot <<- EOF
#Y軸のグリッド線を入れる
set grid y

#凡例の位置(outside)、フォント(Times New Roman,26)、フォントサイズ(26)、凡例の幅調整(spacing)
set key right font 'Times New Roman,26' spacing 1.5
# 目盛りのフォントの変更
set tics font "Times New Roman,25"
#xy軸のラベル設定、フォント(Times New Roman,26)、フォントサイズ(26)、位置調整(offset)
set xlabel "hoge" font 'Times New Roman,26' offset 0.0,-1.0
set ylabel "fuga" font 'Times New Roman,26' offset -1.0,0.0
#図のタイトル
set title "title hogefuga2"

#xy軸の範囲指定、複数のグラフの比較を行う時は原則範囲を揃える
set xrange [20:40]
set yrange [10:1000] 

#png画像を(1024,512)のサイズで出力する
set terminal png size 1024,512

#出力先のファイル指定(相対パス)
set output "./sample2.png"

# withの後に続く描画スタイルの指定(必須)でグラフの種類が決まる
# with lp(linespoints)
# 描画スタイルに続けて、細かい設定を行う 
# lt(line_type):グラフのタイプ
# lw(line_width):グラフの線の太さ
# lc(line_color):グラフの色(lc rgb "red"で色の名前で色指定できる)
# pt(point_type):点のタイプ
# ps:点のサイズ(point_size)
# title:凡例名
# 1つのグラフに複数の結果を載せる場合(1つのプロットファイルに複数のプロットデータが入っている場合)
# 改行する時は、必ず'\'が必要なので注意
 plot "./sample2.plot" using 1:2 with lp lt 1 lw 2 pt 3 ps 2 lc rgb "green" title "hoge",\
"" using 1:3 with lp lt 2 lw 2 pt 4 ps 2 lc rgb "purple" title "fuga",\
"" using 1:4 with lp lt 3 lw 2 pt 5 ps 2 lc rgb "black" title "foo"
EOF

生成されたsample2.png

f:id:doi-t:20150330230421p:plain

もう少し使い勝手を考慮したgnuplotスクリプト

プロットデータは、グラフごとにファイルが分かれていても、同様に1つのグラフに同時に描画することができる

sample3-1.plot

20 100
30 300
40 900

sample3-2.plot

20 150
30 150
40 150

sample3-3.plot

20 0.25
30 0.4
40 0.15

例えば、以下のスクリプトのファイル名をsample3.bashとして、bash sample3.bash sample3.pngと実行するとsample3.pngという名前のグラフが生成される

ここでは、出力される画像のファイル名を引数で渡すようにしている

もし、引数を指定しない場合は、

$ bash sample3.bash
Usage: sample3.bash [output-filename]

と、Usageが出力されるようにしている

sample3-3.plotだけ、プロットデータが小さいことに注意

スケールが大きく異なる場合は、以下のようにY軸を2軸にして出力することで対応することができる

#!/bin/bash

#引数のチェック
if [ $# -ne 1 ]; then
    echo "Usage: $0 [output-filename]"
    exit
fi

gnuplot <<- EOF
set grid y

#フォントサイズだけ指定したい場合は以下のようにフォント名を省略する
set key left font ',26' spacing 1.5
set tics font ",25"
set xlabel "hoge" font ',26'
set ylabel "fuga" font ',26'
set title "title hogefuga2"

set xrange [20:40]
set yrange [10:1000] 

#Y軸を2軸にする
set y2tics
set y2range [0.01:0.5] 

set terminal png size 1024,512

set output "$1"

#y2を使用する場合は'axes x1y2'とする
 plot   "./sample3-1.plot" with lp lt 1 lw 2 pt 3 ps 2 lc rgb "green" title "hoge",\
        "./sample3-2.plot" with lp lt 2 lw 2 pt 4 ps 2 lc rgb "purple" title "fuga",\
        "./sample3-3.plot" axes x1y2 with lp lt 3 lw 2 pt 5 ps 2 lc rgb "black" title "foo"
EOF

生成されたsample3.png

f:id:doi-t:20150330230402p:plain

gnuplotの威力と辛み

何と言ってもプロットデータをプレーンテキストとして扱えるのが良い.例えば、自作のプログラムの実行時間を計測してその結果をグラフにまとめたい場合、プログラム自身やプログラムを起動するスクリプトに実行時間を変数と共にファイルに吐き出させるようにしておけば、そのファイルがそのままgnuplotのプロットファイルとなるので、測定からグラフ化までのフローを全て自動化することができる.また、gnuplotはかなり複雑なグラフも描画可能なので、ほとんどの用途に応えることができる.

ただ、本稿では一所懸命スクリプト化を行っているが、個人的にはデータやグラフを載せる先に応じて、必要なグラフの形が頻繁に変わるので、結局基本使い捨てというか、雛形となるヒアドキュメントを基にコピペ量産して似たようなヒアドキュメントの山をメンテナンスし続けるということが多かった.もっと良いやり方があるのかもしれないが...

勉強会を開く時に期待してはいけないこと

ターミナルのショートカットキーから始まってかなり駆け足でシェルスクリプトの活用例まで全5回分をブログに載せました.全て今から約半年前に私が研究室の後輩に向けて書いたものです.研究室ではこの後に、人様のスライドをお借りしてGit入門なんかもやりましたが、全編通して手応えがあるとは言いがたい結果でした.内容はぶっ飛ばしすぎだし、途中ドキュメント作成が滞って1ヶ月以上空いたし、当然と言えば当然ですが、とにかく人の興味を何かに向けるには想像以上の誠実さとエネルギーが必要であることを学びました.社内勉強会の作り方(1)期待してはいけない10のことに書いてある内容の全て、すなわち以下の項目は、実感を持って真であると今なら言えます.

  • 頑張って考えた企画であれば人が集まるとか期待しない。
  • 勉強会が仕事の役に立つとか期待しない。
  • 誰かが助けてくれるとか期待しない。
  • 急に何かが変わるとか期待しない。
  • 自分に期待しない。

社内勉強会の作り方(1)期待してはいけない10のこと

興味を持ってくれて学習が進み始めた時に最も役立つようにリンク多めのドキュメント作成をと思っていましたし、上記ブログを読む前から期待してはいけないと思っていたのですが*3、やる以上それなりの期待を持つのが人だと思います.だからこそ上記の期待しない心構えは精神衛生上、本当に大事だなと感じています.少なくとも勉強会などというものを、半端な覚悟で"やる"などと言うべきではないことはわかりました.折れて辞めようものなら今度は少ないながらも期待していてくれた人を裏切ることにも繋がります.

と言う訳で、世の勉強会を継続して開催している全ての人に尊敬の念を抱かずには居られないわけであります.

b.hatena.ne.jp

*1:毎日それこそ息するように使っているものから、必要な時に覚えてなくて毎回ググっているものまで、ベタだけどまさに当時これが手元にあればなぁという内容で良くできている。このブログを読んでくれるのも嬉しいけど、何ができて何を調べれば良いかをまず知る目的で一回このドキュメントも一通り読んでおくと、"あれどうやるんだっけなー"などとボヤきつつ当てもなくググる時間を減らせるはず。要チェック。

*2:グラフ生成ツールとして世の中的にどの程度普及しているのか、一般的なのかはわかりません.個人的には便利だけど学習コスト高杉という感想です.他に学習コストが低い良い物があればそちらでも良いと思います.

*3:だからこそ完全自由参加の勉強会というなるべく押し付けがましくない形を取りました