gnuplotに関するいろんなこと
#contents
*リンク [#cbb3fddc]
- [[gnuplot tips (not so Frequently Asked Questions):http://t16web.lanl.gov/Kawano/gnuplot/]]
*基本 [#l86a9f0f]
**起動スクリプト [#c8b115fa]
gnuplot起動時に自動で読み込まれるスクリプトは``.gnuplot``で、カレントディレクトリあるいはホームディレクトリから
読み込まれる。
**グラフの外枠 [#h6a65976]
set border
で、``plot``や``splot``のグラフエリアの枠線のON/OFFを設定可能。
設定の仕方が独特で、コマンドの引数となる整数の各ビットにそれぞれの位置の枠線のON/OFFを指定する。
足し算や引き算も使える。
**軸の長さのバランスとスケール [#v9ddc7ab]
set size
でx,y軸の長さのバランスを変える。
``ratio``に負の数を指定すると、x,y軸のスケール比を変えることができる。
例えば
set size ratio -1
とすると、x軸とy軸が同じ縮尺で表示される。
**グラフの描画位置 [#c270c60f]
set origin
で、プロットの描画起点を調整できる。
**usingによるデータカラムの指定 [#s757ab7e]
``using``は、データファイルから実際にプロット座標値となるx, y(, z)の値を作るのに使われる。
using {<entry> {: <entry> ...}}
として使う。
entryには下の2通りがある。
+ カラム番号 ... 指定した番号のカラムのデータをそのまま使用する。カラム番号は左から右へ、1番から設定される。
+ '(' 式 ')' ... 式の演算結果をデータとして使用する。
式中に現れる``$n`` (``n``は1,2,3...)という文字列は、n番のカラムのデータとして展開される。
``$0``は行番号に展開される。
式では、四則演算はもちろん、三角関数やlogなども利用可能。
**スクリプトに複数のデータを埋め込む [#k35133a2]
スクリプトにデータをねじ込む場合、次のようにして書く。
plot "-"
(データ)
end
このように、データファイルとして"-"を指定する。
データの終点を表すendは、実際には先頭がeであれば何でもいいらしい。
複数のデータを埋め込みたい場合、このようにする。
plot "-" title "data 1", "-" title "data 2"
(データ 1)
end
(データ 2)
end
"-"を指定することによる読み込みは``end``を検出するまで続くので、
``end``で区切ってデータを並べてやればOK。
**対数軸 [#oe976e72]
対数軸を設定したい場合は
set logscale
とする。
**余白の処理 [#i233abb1]
*** PNGファイルの場合 [#oe3d25fd]
ImageMagick付属のconvertコマンドを使うといい。
$ convert -trim infile.png outfile.png
*** EPSファイルの場合 [#b15bd9d2]
eps2epsというコマンドを使うとバウンディングボックスを調整してくれるが、
これだと文字をラスタライズしたりしてあまりよろしくなかったりする。
ということで、eps2epsで生成したファイルからバウンディングボックスだけを取り出して、
元のファイルのバウンディングボックスと置換することにした。
#!/bin/sh
E2E=/usr/bin/eps2eps
EGREP=/bin/egrep
SED=/bin/sed
bb=`$E2E -sOutputFile=- $1 dummy | $EGREP '%%BoundingBox: *[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+$'`
$SED -e "s/^%%BoundingBox:.*\$/$bb/" $1
このスクリプトは、引数で指定したEPSファイルのバウンディングボックスを修正して標準出力に吐き出す。
*** gunplotの機能で調整 [#f05c31e4]
余白の調節は、
set lmargin
set tmargin
set rmargin
set bmargin
でもある程度調節可能。
ただ、いい感じの余白は試行錯誤で見つけるしかなさそう。
** 自前で定義したラインスタイルでプロットする [#s8ecc39f]
ユーザ定義のラインスタイルを使うには
set style increment user
を前もって設定しないといけない。
また、
set style line
で直線のスタイルを定義しておく。
''修正:20091121''
plotコマンド利用時にwithコマンドで明示的にラインスタイルを指定すれば、自前で定義したスタイルでプロット可能。
set style increment userが必要なのは、自前で定義したラインスタイルをデフォルトのスタイルにしたい場合。
** PNGプロットでフォントを指定する [#pc45e382]
pngターミナルでフォント変更をするときはフォントファイル(.ttfとか)のフルパスを指定する。
set terminal png font "/usr/share/fonts/truetype/msttcrefonts/Arial.ttf"
環境変数``GDFONTPATH``にフォントファイルの検索ディレクトリを指定しておくことも可能。
*** デフォルトフォントの設定 [#ndf4027d]
Ubuntu Karmicのgnuplot (4.2.5)におけるPNG terminalでは、どうもデフォルトのTrueTypeフォントがセットされている。
ただ、個人的にはこれまでのデフォルトだったGDライブラリビルトインフォントも好きだったので、
基本的にはそちらを使いたい所だが、どうも普通のやり方ではビルトインフォントを利用する方法がないっぽい。
ビルトインフォントは機能があまりにも制限されているからというのが主な理由のようだが、
かといってこれまでデフォルトになっていた仕様に戻すことができないのはいかがなものか。まあ、いいけど。
- 参考: http://old.nabble.com/png:-selecting-builtin-font-impossible--td22078399.html
** plotデータソースに"" [#r54e176b]
-参考: gnuplot help "special-filenames"
plotのデータソース引数に""を与えると、直前のプロットコマンドのソースを引き継ぐ。
> plot "file.dat" using 1:2 , "" using 1:3
** SVG出力をInkscapeで編集 [#lc6af9b2]
参考:
-http://www.yamamo10.jp/yamamoto/wordpress/?p=46
-https://bugs.launchpad.net/inkscape/+bug/196291
-http://bits.6w9.org/?p=239
set terminal svg
とするとSVG形式でグラフを出すことができる。
SVGで出力するとInkscapeなんかで編集できて便利。
ただ、Inkscape0.46(Ubuntu 8.04, inkscape 0.46-0ubuntu2)にはバグがあるらしく、
gnuplotが吐き出すストロークカラーの設定を解釈できないようだ。
[[LaunchPad:https://bugs.launchpad.net/inkscape/+bug/196291]]にこれを修正するInkscapeプラグインがあるが、
いちいちInkscapeで開いて修正するのはむしろ面倒なので、スクリプトで処理することにした。
http://bits.6w9.org/?p=239
にPerlのスクリプトがあったのでこいつを使わせてもらった。
(20091025追記):~
なんか上記サイトのリンクが切れているので、仕方なくスクリプトを載せることにする。
use warnings;
use strict;
while (<>) {
s/(color:)(.*?)(;\s* stroke:)currentColor/$1$2$3$2/;
print;
}
あと、Inkscape0.47では修正されているみたい。
** スクリプトの途中で設定をデフォルトに戻す [#od897ead]
- 参考: gnuplot help "reset", ".gnuplot", "load"
gunplotスクリプトの途中で``set``コマンドによる設定を全てデフォルトに戻したい場合、
reset
コマンドを使う。
``reset``は``terminal``、``output``、``fontpath``、``loadpath``以外の設定をデフォルトに戻す。
ただ、gnuplot起動時に読み込まれる初期化スクリプト".gnuplot"で``set``コマンドを使っている場合、
この設定も解除されてしまうので、そういうときは``reset``コマンドに続けて
load "~/.gnuplot"
とでもして再度読み込むようにする。
** set labelで任意テキストやポイントを任意位置に出力 [#wbbb61a2]
set label でテキストやポイントを任意の位置に出力できる。
位置の指定の座標系はデフォルトで"first"(第1x軸、第1y軸)が使われる。
出力されるテキストやポイントはデフォルトでプロットの下に出力されるが、
これは"back"が有効になっているせい。
プロットの上に出力させたい場合、"front"を指定する。
**X11出力で複数のウィンドウを開く [#tf0038d8]
set terminal x11 [n]
で、nのところに適当に番号を指定すると、番号毎に独立したウィンドウでプロットを表示してくれる。
wxtターミナルでも可能。
参考: gnuplot help "x11", "wxt"
**データファイル中の文字列をusingで使う。 [#fecae222]
stringcolumn関数を使えばいい。
ちなみにgnuplotでは文字列演算として、連結(.)及び一致比較(eq, ne)を使うことができる。
参考:
- http://www.ss.scphys.kyoto-u.ac.jp/person/yonezawa/contents/program/gnuplot/table.html
- gnuplot help "stringcolumn", "operator binary"
**fillstyle empty [#jecf0c1d]
塗りつぶしのスタイルを決めるfillstyle。
emptyを指定すると塗りつぶさないはずであるが、Version 4.2.5よりも前のバージョンでは背景色を使って塗りつぶしてしまうらしい。
参考: http://takeno.iee.niit.ac.jp/~shige/unix/gnuplot/gpinfo-2009.html#info-20090331
** マクロを使う [#x4cbb38d]
set macros
このコマンドを使うと、文字列変数をコマンドマクロとして使うことができるようになる。
U = "u ($1/1000):($2+$3)"
plot "data1.plot" @U, "data2.plot" @U
@を先頭につけることでマクロ展開される。
** autoscale時の軸の余白 [#s43d8ee8]
- 参考: Gnuplot help "offsets"
autoscaleを使う際、データポイントがボーダー上に乗ってしまって見づらい場合は``set offsets``コマンドでグラフ内の余白を設定することができる。
* ちょっと変わったプロット [#h890daec]
** データファイルから目盛りや凡例のラベル文字列を設定する [#r8dbe6f4]
- 参考: Gnuplot help "datastrings", "using xticlabels"
目盛り(tic)のラベルを数値ではなく、文字列で示したいという時がある。
また、凡例(key)の文字列をデータファイルから読み込んで使いたい時もある。
例えば、次のような成績表的なデータファイル(sample.plot)があるとする。
"Subject|Name" "Ito" "Tanaka" "Watanabe"
"Math" 70 83 78
"English" 67 73 92
"Physics" 81 69 70
"Chemistry" 72 55 78
こういう時、1行目は凡例のラベルとして、1列目はX軸のラベルとして使って棒グラフで整理したくなるだろう。
これを、gnuplotでは、例えばこうする。
set yrange [0:100]
set xrange [-0.5:3.5]
set style data boxes
set style fill solid 1.0
set boxwidth 0.2 relative
set key autotitle columnhead
plot "sample.plot" using ($0-0.25):2, \
"sample.plot" using ($0):3:xticlabels(1), \
"sample.plot" using ($0+0.25):4
#ref(gnuplot_datastrings.png,right,around)
この結果が右図。
1〜5行目の``set``コマンドの羅列は体裁を整えるものなのであまり意味はない。
plotコマンドで人数分のグラフを描画しているが、ポイントは3つ。
- ``using``で``$0``を使ってX軸の値を指定しているが、プロットごとにオフセットを変えることで、
棒グラフが重なってしまうことを避ける。
- ``using``の第3項目に``xticlabels(1)``を指定して、1列目の文字列データをX軸のラベルとして使うことを指定している。
- ``set key autotitle columnhead``を指定すると、データファイルの1行目の各列が凡例ラベルとして扱われる。
なお、``columnhead``はplotコマンドの``title``に指定することも可能。
#clear
** ``xticlabels``で目盛りラベルの出力をまばらにする [#u4433bdd]
gnuplot 4.2で確認。(Ubuntu 8.04のパッケージ gnuplot 4.2.2-1)
x軸の目盛りラベルにデータファイル中の文字列を使う時、普通に``xticlabels``を使うと全ての目盛りラベルが出力されてしまい、
場合によってはグラフがごちゃごちゃになってしまう。
例えば、次のような2都市の気温の変遷のデータ(temperature.plotとする)があるとき、
"Date" "Tokyo" "Osaka"
"4/1" 9.9 9.6
"4/2" 9.8 8.8
"4/3" 12.3 10.6
(中略)
"5/30" 18.4 22.6
"5/31" 19.7 19.6
単に``xticlabels``を使って出力する場合、以下のようなコマンドを叩く。
plot "temperature.plot" using 0:2:xticlabels(1) title 2, \
"temperature.plot" using 0:3 title 3
しかし、これをすると、下の図のように日付ラベルが潰れてしまう。
|&ref(gnuplot_temp_before.png);|
|CENTER:``xticlabels``をそのまま使う場合|f
このような場合は、以下のように``plot``コマンドを叩くとある程度うまく出力できる。
plot "temperature.plot" using ($0 * 5):2:xticlabels(1) every 5::1 notitle lt -2, \
"temperature.plot" using 0:2 title 2 lt 1 pt 1,\
"temperature.plot" using 0:3 title 3 lt 2 pt 2
この結果が下図である。
|&ref(gnuplot_temp_after.png);|
|CENTER:ダミープロットを使う場合|f
ポイントは、
- データラベルを出すために専用のダミープロットをまず出力する。``notitle``と``lt -2``により、グラフや凡例は出力されない。
- ダミープロットに加えて、実際に出力したいプロットを2つ行っている。これらをリアルプロットと呼ぶことにする。
- ダミープロットは``every 5::1``により、2個目から5個おきにデータポイントをとるようにしている。
つまり、データファイルの最初の1行目(凡例ラベルが書いてある)を読み飛ばし、次の行から5行おきにプロットをする。
- ``every``でデータを部分的に取り出した場合、``using``で``$0``としてアクセスできる値は元の行番号などではなく、
あくまでも取り出してきたデータポイントのインデックスとなる。
よって、``using ($0 * 5)``によって、プロット上で本来の間隔になるように調整する。
- ダミープロットでは``using``によってy軸の値は2列目からとるようにしている。
これはリアルプロットに2列目が含まれているからである。
y軸の値を適切に設定しないと、``yrange``に``autoscale``を適用した場合にダミープロットの値も加味されてしまう。
これを防ぐために、ダミープロットのy値はリアルプロットのものを転用するべきである。
問題点として、これをやるとminor ticsが表示されなくなる。
``mxtics``で設定しても``xticlabels``命令がこの設定も上書きしているようだ。
また、``ticlabels``によるticsの設定は持続するらしく、
``ticlabels``を使ったプロットを(設定を変えながら)連続して行うとticsの位置がおかしくなることがある。
それを防ぐために、``ticlabels``を使うプロットの前に、例えば
set xtics autofreq
などとして前の設定をリセットしておくといいようだ。
参考: http://takeno.iee.niit.ac.jp/~shige/unix/gnuplot/gpinfo-2009.html#info-20090216
** 途中が切れている(省略されている)棒グラフ [#vb2878f7]
- 参考: Gnuplot help "margin"
次のようなデータを棒グラフでプロットしようとする。
"A" 34
"B" 13
"C" 632
"D" 28
この場合、"C"のデータだけがやたら大きいので、"C"にグラフの寸法を合わせると他の3つが潰れてしまう。
「"C"だけが例外的に非常に大きい」ということを言いたいのなら、"C"の棒の上方を省略表示するのも一つの手だろう。
こういう時は例えばこうする。
#ref(gnuplot_margin_screen.png,right,around)
set style data boxes
set style fill solid 1.0
set boxwidth 0.7
set lmargin 8
unset key
set ytics 10
set mytics 5
## 下側のプロット
set multiplot
set yrange [0:50]
set ylabel "Value" offset 0,5
set tmargin at screen 0.7
set bmargin at screen 0.07
plot "sample.dat" u 0:2:xticlabel(1)
## 上側のプロット
set yrange [620:640]
unset ylabel
set xtics format ""
set tmargin at screen 0.98
set bmargin at screen 0.728
plot "sample.dat" u 0:2
``multiplot``を使い、同じデータでyrangeの異なる二つのプロットを描画する。
ここで、``set margin at screen``コマンドを使うと二つのプロットを正確に配置できる。
``set margin at screen``では、マージンの幅ではなくマージンの位置をscreen座標で指定する。
``tmargin``と``bmargin``を指定することで、二つのプロットの高さと位置を固定する。
この時、二つのプロットのyrangeの幅の比率とグラフ描画領域の高さの比率を一致させることで、y軸の縮尺を揃えることができる。
また、上側のプロットは``set xtics format ""``として目盛りラベルを消している。
グラフの真ん中にボーダーの線が入るのが気になるのなら、``set border``コマンドでボーダーを消去したり、
``set arrow``コマンドで追加の線を引いたりすればいい。
#clear
** 四角形を描画する [#b10b6485]
任意の位置、任意のサイズの四角形を描画したい時は、``set object``を使う。
例えば、以下の例はグラフ領域全域の背景色をシアンにする。
set object 1 rect from graph 0, graph 0 to graph 1, graph 1 back fc rgb "cyan" fs solid
** filledcurvesでグラフの塗りつぶし [#h65a82e5]
``filledcurves``スタイルで曲線や軸で囲まれた部分の塗りつぶしができる。
plot "sample.plot" using 1:2:3 with filledcurves fill solid 0.4 notitle,\
"sample.plot" using 1:2 with linespoints linewidth 2 linetype 1 title "lower",\
"sample.plot" using 1:3 with linespoints linewidth 2 linetype 2 title "upper"
この例では塗りつぶしの両端を``linespoints``で改めて描画している。
#ref(gnuplot_filledcurves.png)
** fitコマンドで回帰分析 [#i7da9a35]
- 参考: gnuplot help "fit"
gnuplotでは、ユーザが設定した関数のパラメータを回帰分析で推定することができる。
f(x) = a*x + b
fit f(x) "datafile" via a, b
とかやると、変数aとbを設定してくれる。
"datafile"の後にはindexやusingなど、plotコマンドで使う修飾子をつけることができる。
** 3Dプロットの2Dスライスをプロットする [#i06ce47e]
3Dプロットを分析する時に、特定の軸を固定したスライスを見てみたい時がある。
|&ref(slice_3d.png);|&ref(slice_2d.png);|
|3Dプロット|6 < x < 8範囲のスライスプロット|f
こういった2Dスライスは、plotコマンドのusing項をうまく設定すれば出力できる。
例えば、列1(x軸)が[6:8]の範囲のスライスのみを取り出して出力する場合、
plot "hoge.plot" u 2:( $1 >= 6 && $1 <= 8 ? $3 : 1/0)
のようにする。
"1/0"は未定義の値となり、無視される。
結局、3項条件演算子(?:)の条件節が真となるデータ行でのみ、列3(本来のz軸の値)がy軸にプロットされる。
参考:http://ayapin.film.s.dendai.ac.jp/~matuda/Gnuplot/Tips/tips.html
*** 追記:20091121 [#o192f44e]
今まで試したスライスは結果として取り出すデータレコード(行)がファイル中で連続していたため、うまくいっていた。
しかし、取り出すデータレコードがファイル中でとびとびの行に渡っている場合、それらの点を線でつないでくれない(gnuplot 4.2.2で確認)。
この場合、取り出すデータレコードが連続した行に現れるようにデータファイルを整形する必要がある。
gnuplotのデータファイル指定書式"<"を使うと、シェルコマンド結果をデータファイルとして扱うことができる。
そこで例えば、データファイルhoge.plotの2列目をconstにして、1列目に対する3列目のスライスプロットを行うには、このようにする。
plot "< sort -g -k 2 -k 1 hoge.plot" u 1:($2 > 0 && $2 < 1 ? $3 : 1/0)
一旦sortコマンドで2列目データの等しいレコードが固まるようにする('-k 2'オプション)。'-k 1'オプションもつけているのは、こうしないと線の結び方の順序がめちゃくちゃになるから。
・・・もっとスマートな方法があるんだろうか??
データファイルが巨大だとsortの処理だけでもちょっと時間がかかる。
参考: gnuplot help "special-file"
*3次元プロット [#hfee0eba]
3次元プロットには``splot``コマンドを使う。
そのデータファイルは、基本的にx, y, z座標の羅列となる。
**行列プロット [#i8537b04]
行列をプロットする、つまり、zの値が2次元配列の形で
与えられるデータファイルをプロットする場合、
splot "hoge.plot" matrix
のように、``splot``コマンドに``matrix``を与えれば良い。
こうすると、行列から(x, y, z)データを自動的に作成して描画してくれる。
x, yの座標値は、それぞれ0番開始のcolumn(列)番号、row(行)番号が使われる。
これらの値をさらに``using``で加工することも可能。
**グラデーションによる線描画 [#b6685fe0]
``splot``コマンドに、``with lines palette``オプションを与えると、
プロット線をz値に応じたグラデーションで描ける。
**グラデーションの色変更 [#xc932b30]
``set palette``でグラデーションで使う色づかいを変更できる。
プロット値の範囲が不明なら、
set palette rgbformulae
で、zの値と色との対応を関数化すると良い。
**陰線消去 [#afe72a5f]
手前の面に隠れた線を描画しないようにするなら
set hidden3d
とする。
**カラーボックス [#sbc7fc68]
3次元のグラデーションプロットを行った場合、
色と値の対応付けを表示するボックスは``colorbox``と呼ばれる。
set colorbox
や
set cbtics
などで設定可能。
**z軸のゼロ点の位置 [#s3d91550]
z軸のゼロ点の位置をxy平面にくっつけたいのなら、
set ticslevel 0
とする。
**3次元データを平面プロット [#ndee23d8]
3次元データを、高さを色の変化として表現することで
平面にプロットするには、
set pm3d map
とする。
**3次元データの平面プロットでファイルに出力 [#qa9b89bf]
グラデーションを使ったプロットをファイルに出力する場合は若干の注意が必要。
PNGに出力する場合、
set terminal png truecolor
として、``truecolor``を指定しないと表示色がバグる。
EPSの場合、
set terminal postscript eps enhanced color
などとする必要がある。
**pm3d mapで極力データに"忠実な"画像を出力する [#tdd9b203]
gnuplotで2変数関数データファイルを
set pm3d map
として2Dカラーマップとして表示することが多いのだが、その時、見えるはずのデータが見えないという現象に遭遇した。
そういうことが起こらないようにするために、現時点で分かったことを書いておく。
- ''corners2color c1などを指定''
pm3dによるsplotの色つけは、"点"ではなく、"面"に対して行われる。
原則として、各面の端点のz座標値を元に色の値が決められ、その色の値が実際の色にマップされる。
デフォルトでは、4つの端点の平均値を色の値として使う。
そのため、周囲に比べて極端に高い点が1点だけある場合でも、平均処理によってコントラストが低下する。
set pm3dのオプションで"corners2color"を使うと、端点から色の値をどう計算するかを指定できる。ここで、
set pm3d corners2color c1
とすると、4つの端点のうちの一つの値をそのまま色の値として使うようになる(同様に、c2, c3, c4を指定可能)。
これを指定すれば、データポイントに忠実な色使いで画像を出力できるが、仕様上、端のデータポイントは一部利用されなくなる。
- ''zrangeはcbrangeよりも広く''
zrange, cbrangeを指定して画像出力範囲をクリップする場合、zrangeはcbrangeよりも広くとった方が無難だと思われる。
面を構成する4つの端点のうち、どれか一つでもzrangeの外側に出てしまうと、その面は描画されないようだ(正確には違うかも)。
逆に、zrangeを極端に広くとった場合でも、cbrangeからはみ出た点は自動的にcbrangeの端の色で描画される。
・・・でもこれをやるとEPS形式で出力した時にデータサイズがどえらいことになったりするので、ほどほどに。
PNG形式何かで出力する分にはzrangeは極端に広くとってしまえばよさそうだ。