• 差分
  • リロード
  • 一覧
  • 最終更新のRSS

gnuplotに関するいろんなこと

リンク

基本

起動スクリプト

gnuplot起動時に自動で読み込まれるスクリプトは.gnuplotで、カレントディレクトリあるいはホームディレクトリから 読み込まれる。

グラフの外枠

set border

で、plotsplotのグラフエリアの枠線のON/OFFを設定可能。

設定の仕方が独特で、コマンドの引数となる整数の各ビットにそれぞれの位置の枠線のON/OFFを指定する。 足し算や引き算も使える。

軸の長さのバランスとスケール

set size

でx,y軸の長さのバランスを変える。

ratioに負の数を指定すると、x,y軸のスケール比を変えることができる。 例えば

set size ratio -1

とすると、x軸とy軸が同じ縮尺で表示される。

グラフの描画位置

set origin

で、プロットの描画起点を調整できる。

usingによるデータカラムの指定

usingは、データファイルから実際にプロット座標値となるx, y(, z)の値を作るのに使われる。

using {<entry> {: <entry> ...}}

として使う。 entryには下の2通りがある。

  1. カラム番号 ... 指定した番号のカラムのデータをそのまま使用する。カラム番号は左から右へ、1番から設定される。
  2. '(' 式 ')' ... 式の演算結果をデータとして使用する。 式中に現れる$n (nは1,2,3...)という文字列は、n番のカラムのデータとして展開される。 $0は行番号に展開される。 式では、四則演算はもちろん、三角関数やlogなども利用可能。

スクリプトに複数のデータを埋め込む

スクリプトにデータをねじ込む場合、次のようにして書く。

plot "-"
(データ)
end

このように、データファイルとして"-"を指定する。 データの終点を表すendは、実際には先頭がeであれば何でもいいらしい。

複数のデータを埋め込みたい場合、このようにする。

plot "-" title "data 1", "-" title "data 2"
(データ 1)
end
(データ 2)
end

"-"を指定することによる読み込みはendを検出するまで続くので、 endで区切ってデータを並べてやればOK。

対数軸

対数軸を設定したい場合は

set logscale

とする。

余白の処理

PNGファイルの場合

ImageMagick付属のconvertコマンドを使うといい。

$ convert -trim infile.png outfile.png

EPSファイルの場合

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の機能で調整

余白の調節は、

set lmargin
set tmargin
set rmargin
set bmargin

でもある程度調節可能。 ただ、いい感じの余白は試行錯誤で見つけるしかなさそう。

自前で定義したラインスタイルでプロットする

ユーザ定義のラインスタイルを使うには

set style increment user

を前もって設定しないといけない。

また、

set style line

で直線のスタイルを定義しておく。

修正:20091121

plotコマンド利用時にwithコマンドで明示的にラインスタイルを指定すれば、自前で定義したスタイルでプロット可能。 set style increment userが必要なのは、自前で定義したラインスタイルをデフォルトのスタイルにしたい場合。

PNGプロットでフォントを指定する

pngターミナルでフォント変更をするときはフォントファイル(.ttfとか)のフルパスを指定する。

set terminal png font "/usr/share/fonts/truetype/msttcrefonts/Arial.ttf"

環境変数GDFONTPATHにフォントファイルの検索ディレクトリを指定しておくことも可能。

デフォルトフォントの設定

Ubuntu Karmicのgnuplot (4.2.5)におけるPNG terminalでは、どうもデフォルトのTrueTypeフォントがセットされている。

ただ、個人的にはこれまでのデフォルトだったGDライブラリビルトインフォントも好きだったので、 基本的にはそちらを使いたい所だが、どうも普通のやり方ではビルトインフォントを利用する方法がないっぽい。

ビルトインフォントは機能があまりにも制限されているからというのが主な理由のようだが、 かといってこれまでデフォルトになっていた仕様に戻すことができないのはいかがなものか。まあ、いいけど。

plotデータソースに""

  • 参考: gnuplot help "special-filenames"

plotのデータソース引数に""を与えると、直前のプロットコマンドのソースを引き継ぐ。

> plot "file.dat" using 1:2 , "" using 1:3

SVG出力をInkscapeで編集

参考:

set terminal svg

とするとSVG形式でグラフを出すことができる。 SVGで出力するとInkscapeなんかで編集できて便利。 ただ、Inkscape0.46(Ubuntu 8.04, inkscape 0.46-0ubuntu2)にはバグがあるらしく、 gnuplotが吐き出すストロークカラーの設定を解釈できないようだ。 LaunchPadにこれを修正する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では修正されているみたい。

スクリプトの途中で設定をデフォルトに戻す

  • 参考: gnuplot help "reset", ".gnuplot", "load"

gunplotスクリプトの途中でsetコマンドによる設定を全てデフォルトに戻したい場合、

reset

コマンドを使う。 resetterminaloutputfontpathloadpath以外の設定をデフォルトに戻す。 ただ、gnuplot起動時に読み込まれる初期化スクリプト".gnuplot"でsetコマンドを使っている場合、 この設定も解除されてしまうので、そういうときはresetコマンドに続けて

load "~/.gnuplot"

とでもして再度読み込むようにする。

set labelで任意テキストやポイントを任意位置に出力

set label でテキストやポイントを任意の位置に出力できる。 位置の指定の座標系はデフォルトで"first"(第1x軸、第1y軸)が使われる。

出力されるテキストやポイントはデフォルトでプロットの下に出力されるが、 これは"back"が有効になっているせい。 プロットの上に出力させたい場合、"front"を指定する。

X11出力で複数のウィンドウを開く

set terminal x11 [n]

で、nのところに適当に番号を指定すると、番号毎に独立したウィンドウでプロットを表示してくれる。 wxtターミナルでも可能。

参考: gnuplot help "x11", "wxt"

データファイル中の文字列をusingで使う。

stringcolumn関数を使えばいい。 ちなみにgnuplotでは文字列演算として、連結(.)及び一致比較(eq, ne)を使うことができる。

参考:

fillstyle empty

塗りつぶしのスタイルを決めるfillstyle。 emptyを指定すると塗りつぶさないはずであるが、Version 4.2.5よりも前のバージョンでは背景色を使って塗りつぶしてしまうらしい。

参考: http://takeno.iee.niit.ac.jp/~shige/unix/gnuplot/gpinfo-2009.html#info-20090331

マクロを使う

set macros

このコマンドを使うと、文字列変数をコマンドマクロとして使うことができるようになる。

U = "u ($1/1000):($2+$3)"
plot "data1.plot" @U, "data2.plot" @U

@を先頭につけることでマクロ展開される。

autoscale時の軸の余白

  • 参考: Gnuplot help "offsets"

autoscaleを使う際、データポイントがボーダー上に乗ってしまって見づらい場合はset offsetsコマンドでグラフ内の余白を設定することができる。

ちょっと変わったプロット

データファイルから目盛りや凡例のラベル文字列を設定する

  • 参考: 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
gnuplot_datastrings.png

この結果が右図。 1〜5行目のsetコマンドの羅列は体裁を整えるものなのであまり意味はない。 plotコマンドで人数分のグラフを描画しているが、ポイントは3つ。

  • using$0を使ってX軸の値を指定しているが、プロットごとにオフセットを変えることで、 棒グラフが重なってしまうことを避ける。
  • usingの第3項目にxticlabels(1)を指定して、1列目の文字列データをX軸のラベルとして使うことを指定している。
  • set key autotitle columnheadを指定すると、データファイルの1行目の各列が凡例ラベルとして扱われる。 なお、columnheadはplotコマンドのtitleに指定することも可能。

xticlabelsで目盛りラベルの出力をまばらにする

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

しかし、これをすると、下の図のように日付ラベルが潰れてしまう。

xticlabelsをそのまま使う場合
gnuplot_temp_before.png

このような場合は、以下のように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

この結果が下図である。

ダミープロットを使う場合
gnuplot_temp_after.png

ポイントは、

  • データラベルを出すために専用のダミープロットをまず出力する。notitlelt -2により、グラフや凡例は出力されない。
  • ダミープロットに加えて、実際に出力したいプロットを2つ行っている。これらをリアルプロットと呼ぶことにする。
  • ダミープロットはevery 5::1により、2個目から5個おきにデータポイントをとるようにしている。 つまり、データファイルの最初の1行目(凡例ラベルが書いてある)を読み飛ばし、次の行から5行おきにプロットをする。
  • everyでデータを部分的に取り出した場合、using$0としてアクセスできる値は元の行番号などではなく、 あくまでも取り出してきたデータポイントのインデックスとなる。 よって、using ($0 * 5)によって、プロット上で本来の間隔になるように調整する。
  • ダミープロットではusingによってy軸の値は2列目からとるようにしている。 これはリアルプロットに2列目が含まれているからである。 y軸の値を適切に設定しないと、yrangeautoscaleを適用した場合にダミープロットの値も加味されてしまう。 これを防ぐために、ダミープロットの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

途中が切れている(省略されている)棒グラフ

  • 参考: Gnuplot help "margin"

次のようなデータを棒グラフでプロットしようとする。

"A" 34
"B" 13
"C" 632
"D" 28

この場合、"C"のデータだけがやたら大きいので、"C"にグラフの寸法を合わせると他の3つが潰れてしまう。 「"C"だけが例外的に非常に大きい」ということを言いたいのなら、"C"の棒の上方を省略表示するのも一つの手だろう。

こういう時は例えばこうする。

gnuplot_margin_screen.png
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座標で指定する。 tmarginbmarginを指定することで、二つのプロットの高さと位置を固定する。 この時、二つのプロットのyrangeの幅の比率とグラフ描画領域の高さの比率を一致させることで、y軸の縮尺を揃えることができる。

また、上側のプロットはset xtics format ""として目盛りラベルを消している。

グラフの真ん中にボーダーの線が入るのが気になるのなら、set borderコマンドでボーダーを消去したり、 set arrowコマンドで追加の線を引いたりすればいい。

四角形を描画する

任意の位置、任意のサイズの四角形を描画したい時は、set objectを使う。 例えば、以下の例はグラフ領域全域の背景色をシアンにする。

set object 1 rect from graph 0, graph 0 to graph 1, graph 1 back fc rgb "cyan" fs solid

filledcurvesでグラフの塗りつぶし

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で改めて描画している。

gnuplot_filledcurves.png

fitコマンドで回帰分析

  • 参考: gnuplot help "fit"

gnuplotでは、ユーザが設定した関数のパラメータを回帰分析で推定することができる。

f(x) = a*x + b
fit f(x) "datafile" via a, b

とかやると、変数aとbを設定してくれる。 "datafile"の後にはindexやusingなど、plotコマンドで使う修飾子をつけることができる。

3Dプロットの2Dスライスをプロットする

3Dプロットを分析する時に、特定の軸を固定したスライスを見てみたい時がある。

3Dプロット6 < x < 8範囲のスライスプロット
slice_3d.pngslice_2d.png

こういった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

今まで試したスライスは結果として取り出すデータレコード(行)がファイル中で連続していたため、うまくいっていた。 しかし、取り出すデータレコードがファイル中でとびとびの行に渡っている場合、それらの点を線でつないでくれない(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次元プロット

3次元プロットにはsplotコマンドを使う。 そのデータファイルは、基本的にx, y, z座標の羅列となる。

行列プロット

行列をプロットする、つまり、zの値が2次元配列の形で 与えられるデータファイルをプロットする場合、

splot "hoge.plot" matrix

のように、splotコマンドにmatrixを与えれば良い。 こうすると、行列から(x, y, z)データを自動的に作成して描画してくれる。

x, yの座標値は、それぞれ0番開始のcolumn(列)番号、row(行)番号が使われる。 これらの値をさらにusingで加工することも可能。

グラデーションによる線描画

splotコマンドに、with lines paletteオプションを与えると、 プロット線をz値に応じたグラデーションで描ける。

グラデーションの色変更

set paletteでグラデーションで使う色づかいを変更できる。 プロット値の範囲が不明なら、

set palette rgbformulae

で、zの値と色との対応を関数化すると良い。

陰線消去

手前の面に隠れた線を描画しないようにするなら

set hidden3d

とする。

カラーボックス

3次元のグラデーションプロットを行った場合、 色と値の対応付けを表示するボックスはcolorboxと呼ばれる。

set colorbox

set cbtics

などで設定可能。

z軸のゼロ点の位置

z軸のゼロ点の位置をxy平面にくっつけたいのなら、

set ticslevel 0

とする。

3次元データを平面プロット

3次元データを、高さを色の変化として表現することで 平面にプロットするには、

set pm3d map

とする。

3次元データの平面プロットでファイルに出力

グラデーションを使ったプロットをファイルに出力する場合は若干の注意が必要。

PNGに出力する場合、

set terminal png truecolor

として、truecolorを指定しないと表示色がバグる。

EPSの場合、

set terminal postscript eps enhanced color

などとする必要がある。

pm3d mapで極力データに"忠実な"画像を出力する

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は極端に広くとってしまえばよさそうだ。

Last-modified: 2013-02-17 (日) 11:52:47 (2373d)