gnuplotで数値をファイルに書き出す(table)

set tableコマンドの基本

set table "***"コマンドを使ってから関数やデータをプロットすると、プロットされるべきデータがファイル"***"に保存されます。例えば、以下のようなスクリプトを実行すると、sin.tableというファイルが作成されます。

set table "sin.table"
plot sin(x)
unset table

sin.tableの中身は以下のようなテキストデータファイルになっていて、1列目にxの値が、2列目にyの値(この例ではsin(x))がそれぞれ入っています。

3列目のiなどの文字はそのデータ点がxrangeyrangeに入っているかどうかを表しています。あるデータ点がこれらのrangeに入っていればiが、入っていなければoが、定義されていない値であればuが3列目に保存されます。例えば上で作ったsin.tableを用いた以下のようなスクリプトを実行すると、新しく作成されたsin2.tableの中身の3列目はほとんどoであり、1列目が1以上2以下のデータ点のみ3列目がiになります。

set xrange [1:2]
set table "sin2.table"
plot "sin.table"
unset table

余談ですが、この3列目のiとかostringcolumn()関数を用いると捕まえることができて、例えば以下のように3列目の文字で場合分けしてプロットすることができます。なお、stringcolumn()関数の引数にはダラーマーク$付の整数ではなく普通の整数を入れるべきだという点に注意が必要です。

plot "sin2.table" using 1:(stringcolumn(3) eq "i" ? $2 : 1/0),\
     "sin2.table" using 1:(stringcolumn(3) eq "o" ? $2 : 1/0)

たくさんのデータを保存したい場合

普通にset table "***"してplotするだけだと、2列のデータしか保存できません。もっとたくさんの列のデータを保存したい場合は、以下のような手段を用います。

splotを使う

以下の例のようにset table "***"のあと、splotすると、3列のデータ(+4列目の文字)を保存できます。

set table "3-column.table"
splot "sin.table" using 1:2:(cos($1))
unset table

with ***を使う

plotsplotwithオプションによっては、さらに多くのデータをset tableで保存することができます。例えば、with vectorを使うと、plotの場合は4列、splotの場合は6列のデータが保存できます。

set table "6-column.table"
splot "sin.table" using 0:1:2:(cos($1)):(exp($1)):(log(abs($1))) with vectors
unset table

with labelsを使う

with ***を使うやり方では現状6列までのデータしか保存できないようです。それ以上のデータを保存したい場合は、あまりまともな方法ではありませんが、with labelsを使って文字列として保存してしまうという力技があります。例えば10列のデータを保存したい場合は以下のようにします。

set table "10-column.table"
plot "sin.table" using 1:(sin($1+1)):(sprintf("% g % g % g % g % g % g % g % g",\
     sin($1+2), sin($1+3), sin($1+4), sin($1+5), sin($1+6), sin($1+7),\
     sin($1+8), sin($1+9))) with labels
unset table

このようにすると確かに下図のように10列のデータが保存されていることがわかります。

ただし、問題点は2列目と3列目の間に引用符"が入ってしまっている点です。このため、この方法で吐き出したデータファイルを普通の方法でプロットしようとすると、引用符以降が文字列として解釈されてしまいエラーが出てしまいます。これを回避するには、このデータファイルをプロットするときにusingの後にフォーマット文字列を入れる必要があります。

set style data lp
plot "10-column.table" using 1:2 "%lf %lf  \"%*lf %*lf %*lf %*lf %*lf %*lf %*lf %*lf\"",\
     "10-column.table" using 1:2 "%lf %*lf \"%lf  %*lf %*lf %*lf %*lf %*lf %*lf %*lf\"",\
     "10-column.table" using 1:2 "%lf %*lf \"%*lf %lf  %*lf %*lf %*lf %*lf %*lf %*lf\"",\
     "10-column.table" using 1:2 "%lf %*lf \"%*lf %*lf %lf  %*lf %*lf %*lf %*lf %*lf\"",\
     "10-column.table" using 1:2 "%lf %*lf \"%*lf %*lf %*lf %lf  %*lf %*lf %*lf %*lf\"",\
     "10-column.table" using 1:2 "%lf %*lf \"%*lf %*lf %*lf %*lf %lf  %*lf %*lf %*lf\"",\
     "10-column.table" using 1:2 "%lf %*lf \"%*lf %*lf %*lf %*lf %*lf %lf  %*lf %*lf\"",\
     "10-column.table" using 1:2 "%lf %*lf \"%*lf %*lf %*lf %*lf %*lf %*lf %lf  %*lf\"",\
     "10-column.table" using 1:2 "%lf %*lf \"%*lf %*lf %*lf %*lf %*lf %*lf %*lf %lf\""

もしawkなどの外部プログラムが使えれば、それを用いてデータファイルから引用符を外した新しいファイルを作成し、通常の方法でプロットできるようにすることもできます。

gawkcommand= sprintf("gawk \"{gsub(/[\\\"]/, \\\"\\\"); print > \"%s\";}\" %s", \
     "10-column-2.table", "10-column.table")
print gawkcommand
system(gawkcommand)

上のような内容をgnuplotスクリプトに付け加え、外部プログラムgawk(awkの一種)にデータファイルを処理させます。すると下のように"が取れたデータファイルが生成できます。

このファイルは実際にusingのあとにフォーマット文字列を入れなくてもgnuplotでプロットすることができます。

plot "10-column-2.table" u 1:2, "" u 1:3, "" u 1:4, "" u 1:5