ページが長いので「しおり」の仕組みを用意してみました。
「しおり用」と書かれた所をクリックしてからブックマークに入れると、
それはページの先頭ではなく、その箇所へのブックマークになります。
(03/03 2006)
少し前からアナウンスされていた Lua terminal なるものが CVS 版に追加されました。 これのマニュアルも含めて、CVS マニュアルの日本語訳を更新しておきます。
ただ、なんかすぐまた更新されそうな雰囲気ですが、 まあクリスマスプレゼントとして (^^) 一応公開しておきます。2 ちゃんねるの掲示板「gnuplot を使おう。その 2」(アドレスは リンクリスト 参照) に書かれた情報について、多少気になるものがありましたので、 少し書いておきます。
線の色と線の種類 (実線、破線、点線) を独立に指定できないか、 という質問がありました (452)。
出力形式として PostScript (eps) を使用しているらしいですが、 それなら gnuplot-4.2 以降では以下のように linetype (lt)、 linecolor (lc) を別々に指定することで行えます:
set term post eps color dashed 22
set out 'test.eps'
set yrange [0:10]
set pointsize 3
a = 3
str(i) = sprintf("line type %d",i)
plot \
1 title str(1) lw a lt 1 lc rgb "black",\
2 title str(2) lw a lt 2 lc rgb "red",\
3 title str(3) lw a lt 3 lc rgb "blue",\
4 title str(4) lw a lt 4 lc rgb "#008800",\
5 title str(5) lw a lt 5 lc rgb "#008888",\
6 title str(6) lw a lt 6 lc rgb "#888800"
set out
原点を分かるようにするために、黒丸を書きたいのですが、 という質問がありました (465)。
これに対して、以下のような回答がありました。
plot "< echo 0 0"これだと、確かに (0,0) のところに点が書かれるのですが、 デフォルトでは黒丸ではありませんから、以下のようにする必要があります (ついでに sin(x) も同時に書く例にしてみます)。
plot "< echo 0 0" pt 7 ps 3 lc rgb "black" notitle, sin(x)しかし、これはパイプ入力が使えない、 あるいは echo を外部コマンドとして使えない環境では行えません。 そのような場面でも共通に使える手段として、 '-' によるインラインデータの利用があります:
plot '-' pt 7 ps 3 lc rgb "black" notitle, sin(x)さらに、CVS 版の gnuplot なら set object circle で plot とは別に 円を書くことができます:
0 0
e
set object circle at 0,0 size graph 0.01 fc rgb "black" fs solid 1.0この場合は、サイズもグラフの相対サイズとして指定できますし、 plot と独立に書けるのでより有用だろうと思います。
plot sin(x)
10-23 が扱えない、という質問がありました (468)。 これは、365 と同じ話 (cf. 「情報やメモ (08/24 2008)」) と同じ話です。 もちろん 1e-23 という書き方でも大丈夫だという意見もありました。
2 ちゃんねるの掲示板「gnuplot を使おう。その 2」(アドレスは リンクリスト 参照) に書かれた情報について、多少気になるものがありましたので、 少し書いておきます。
バイナリデータを gnuplot に処理させたいが、 1 行のデータがいくつであるか、という指定がわからない、 という質問がありました (448)。
gnuplot のバージョンが書いてないので的確な回答はできませんが、 いずれもオンラインマニュアルを見ればわかると思います。 gnuplot-4.0 以前の場合は、バイナリデータ形式が固定されていて、 その先頭に各孤立線を形成するデータブロックのデータ数を記述します。
gnuplot-4.2 (以降) では、 そのバイナリ形式は matrix binary (単に binary と指定) として継承されていますが、 それ以外のバイナリ形式もサポートされるようになりました。 元記事の人の、x1,y1,z1,x2,y2,z2,... のように データが並んでいる形式のデータの場合は、 以下のように record keyword で指定すればうまく描画できるでしょう:
splot 'data' binary format='%double' record=10x20 w lprecord の指定の 10 の方が、データブロック内のデータ数 (テキストデータの場合の 1 行の空行毎のデータ行数)、 20 の方が、そのデータブロックの総数を意味します。 20 の方は、適当に大きな数字でも構いません。 もちろん using 指定もできます (splot の場合デフォルトが using 1:2:3)。
以下のような関数を xrange [-300:20] (yrange [0:200]) で描画させると、 本来は x 軸まで届くグラフなのに、 それが x 軸よりやや上のところで切れている、 という質問がありました (449):
f(x) = (((19**(0.5)-1)**2)*10*(10-x))**0.5** で指数を多用して書かれていますが、 0.5 乗を sqrt(x) (平方根) を使って書き直せば、 上の式は以下のように変形できます。
g(x) = (15269.5449 - (x + 153.57)**2)**0.5
a=sqrt(19.0)-1.0これを見てわかるように、 f(x) は sqrt(x) の定数倍を x 軸に関して反転して平行移動したもの、 g(x) は中心が (-c,0) で半径が b であるような円の上半分、 となっています。
b=123.57
c=153.57
f(x) = a*sqrt(10.0)*sqrt(10.0-x)
g(x) = sqrt(b*b-(x+c)*(x+c))
このような関数は、確かに定義域の範囲 (f(x) は x≦10.0、g(x) は -b-c≦x≦b-c) で 0 以上の値を取り、 その端では y=0 になるので、本来ならグラフが x 軸まで伸びるはずです。 しかし、これらの関数は、その y=0 になるところでは微分係数の値が無限大、 すなわち接線の傾きが y 軸に平行になっています。 x 軸まで伸びてくれないようにはっきりと見えるのは、 実はそれが原因です。
gnuplot は関数描画では、x の範囲を一定幅で分割し、 その分点での関数の値を計算し、その点を折れ線で結んでいますが、 ルートの中が負になるような定義域以外の点は、 除外点としてそれとの線を結ばないようにします。 もし、x の分点が丁度定義域の端にあれば、 そこまでグラフが伸びるのですが、 分割区間が定義域の端をまたいでいる場合は、 その分割区間では線分が引かれずにそこでグラフが切れてしまいます。 本来ならば、連続関数ではその分割区間の両端の点の y の値は それなりに 0 に近いはずなので、 そこでグラフが切れてしまってもそれほど x 軸とは離れないはずなのですが、 そこでの接線の傾きが無限大の場合は、 かなり小さく分割しても x 軸とは離れてしまいます。
解決策としては、次のような 2 つの方法が示されていました。
前者は、デフォルトではサンプル点数 (= x 方向の分割数) が 100 なので、 それを増やすという方法で、これでそれなりに改善させることは可能ですが、 やはり分点が丁度定義域の端になければやはり x 軸まで 丁度伸びることはありません。
後者は、y の微分係数が定義域の端で無限大にはならないような パラメータを取って書けばよいだろう、ということだと思いますが、 f(x) の方は、例えば逆関数を考えて x を t の二次関数、y を t の一次関数とする手がありますし、 g(x) の方は、例えば中心角をパラメータとする手があります。 ただ、f(x),g(x) を同時に書くとなると、 そのパラメータの選択もそれなりに面倒になります。
set sample と set xrange をうまく調整して、 丁度分点が定義域の端にくるようにする、 という手もあるかもしれませんが、 これも 2 つの関数を同時に表示しようとすると うまくいくようにするのは難しいでしょう。
手っ取り早い方法で、なおかつ y=0 までちゃんと届くグラフを書くには、 定義域外では 0 以下の値を取るように関数を拡張する、 という方法があります。
d=-1.0このようにすると、この F(x), G(x) は すべての x に対して定義されますのでグラフが切れてしまうことは ありませんし、定義域外では 0 以下の値なので、 yrange が [0:200] の元ではその x 軸の下のグラフは表示されません。 もちろん、d=0.0 と設定するのが最もまともな方法なのですが、 この場合は定義域外のグラフが x 軸と重なって一応表示されることになります (重なっているので、細い線で描画するなら普通は見えません)。
F(x)=(x>10.0)? d : f(x)
G(x)=(x<-b-c || x>b-c)? d : g(x)
「情報やメモ (11/16 2008)」 で紹介した、CVS 版 gnuplot の eval に iteration 機能を追加するパッチの 改良版 (eval-for2.diff) ですが、gnuplot で精力的に開発に関わっている Juergen Wieferink さんから修正したパッチを送ってもらいました。
前のパッチ (eval-for2.diff) は、 構文解析の途中でエラーが起きたときに内部変数が うまくリセットされない問題があったのですが、 今度のはそれもうまくいくようで、それなりに安定して動作するようです。
2 ちゃんねるの掲示板「gnuplot を使おう。その 2」(アドレスは リンクリスト 参照) に書かれた情報について、多少気になるものがありましたので、 少し書いておきます。
球を 3 次元で表現し、アニメーション化したいという質問があり (422, 436)、 それに対して以下のような意見がありました。
確かに、gnuplot ではあまりきれいな球は書けず、 レイトレーシングのようなソフトなどにはかないません。 しかし、parametric mode を使えば一応球も書けます:
set parametricよって、あまりきれいでなくてよいなら、 まあ gnuplot でもできなくはありません。
set hidden3d
set isosamples 30,30
set urange [0:2*pi]
set vrange [-0.5*pi:0.5*pi]
x1=0.0; y1=0.0; z1=0.0 # 中心 1 の座標
x2=1.0; y2=2.0; z2=3.0 # 中心 2 の座標
splot x1+cos(u)*cos(v),y1+sin(u)*cos(v),z1+sin(v),\
x2+cos(u)*cos(v),y2+sin(u)*cos(v),z2+sin(v)
また、sleep に相当するものがない、というのは間違いで、 "pause [num]" で sleep に相当することが行えます。 gnuplot のバージョンと環境によっては、非整数秒のスリープも可能です。
またアニメーションも、 使用している gdlib と gnuplot のバージョンによっては、 gif アニメーション画像を gnuplot 単体で作れます。 これだと pause を使ったアニメーション (x11 terminal 等) よりも、 マシンの性能に依存しないアニメーション画像を作成できます。
ただ、元記事の方によると、半径は固定で、 中心はデータファイルから与えたいようで、そのデータは
ある時刻の 1 つ目の球の x,y,z 座標のような形式になっているそうです。 しかし、gnuplot は、関数式の描画は関数式として描画し、 データはデータとして描画しますので、 関数式の一部分のパラメータ (例えば上の xc,yc,zc) をデータから読んで描画することは基本的にはできません。 よって、例えば awk (環境は Linux だそうなので標準的にあるはず) を利用して、 各データに対する gnuplot コマンド列を生成してやる、 などの必要があります。 まあそれだと、結局他のプログラム言語から gnuplot を呼び出すのと それほど変わらないことにもなるかもしれません。
同じ時刻の 2 つ目の球の x,y,z 座標
同じ時刻の 3 つ目の球の x,y,z 座標
空行
次の時刻の 1 つ目の球の x,y,z 座標
同じ時刻の 2 つ目の球の x,y,z 座標
同じ時刻の 3 つ目の球の x,y,z 座標
空行
...
x の範囲 (xrange) は autoscale として、 それによって決定された範囲と同じ範囲を yrange として使用したいのですが、 という質問がありました (443)。
それに対して、writeback と restore でできないか、という意見がありましたが、 これは x の範囲を y の範囲として取得するものではないので 残念ながらそれではできません。 よって、4.2 以前の gnuplot では autoscale で決定された値を save で保存した後で、それを何らかの方法で取得するしか手はなかったのですが、 CVS 版では gnuplot の内部変数値を GPVAL_* という名前の 読み出し専用の変数で使用できるようになっていますので、 それを使えば可能です。
plot 'data' w l lt -2 notitle # ダミー描画使用できる GPVAL_* 変数は、show variable GPVAL_ で確認できます (CVS 版のみ)。
set autoscale yfix # 指定された通りの範囲で描画させる
set yrange [GPVAL_X_MIN:GPVAL_X_MAX]
plot 'data' w l # 本描画
「情報やメモ (11/08 2008)」 で紹介した、CVS 版 gnuplot の eval に iteration 機能を追加するパッチ (eval-for1.diff) ですが、gnuplot 開発元に送ったところ、 再帰的な呼び出しに対応していない、と意見が来ました。 ということで、少し改良したものを作ってみました。
まだあまり完成度は高くないのですが、 とりあえず iteration の入れ子を可能にしていて、 それにより以下のようなコマンドが使えるようになります:
eval for [i=1:3] \この前者は、
sprintf("eval for [j=1:3] sprintf(\"x%d%%d = %d+j\",j)", i,i)
eval for [i=1:3] sprintf("set for [j=1:3] arrow from %d,j rto 1,1",i)
x11 = 1+1 ; x12 = 1+2 ; x13 = 1+3を行い、また、後者は実質的に
x21 = 2+1 ; x22 = 2+2 ; x23 = 2+3
x31 = 3+1 ; x32 = 3+2 ; x33 = 3+3
set arrow from 1,1 rto 1,1; set arrow from 1,2 rto 1,1; set arrow from 1,3 rto 1,1を行います。 2 重配列や 2 次元的な arrow を規則的に設定する場合には便利かもしれません。
set arrow from 2,1 rto 1,1; set arrow from 2,2 rto 1,1; set arrow from 2,3 rto 1,1
set arrow from 3,1 rto 1,1; set arrow from 3,2 rto 1,1; set arrow from 3,3 rto 1,1
(cf. 「情報やメモ (11/18 2008)」)
gnuplot Q&A 掲示板 で、関数の和に関する質問がありました (1929 の記事 「数列の和の計算方法」)。 gnuplot は数式処理ソフトではないので、 級数などを表す仕組みなどは持っていませんが、 再帰定義を利用すると、多少はそれが行えます。 例えば、
f(x,y) = sin(x*y)のようにすると、g(x,i) の値が使われるときに
g(x,i) = (i>0) ? g(x,i-1)+f(x,i) : 0
g(x,i) = f(x,1)+f(x,2)+...+f(x,i)のように展開されます。 例えば、以下のような教科書的なサンプルもこれを利用して作成できます:
set zeroaxis # のこぎり波のフーリエ級数 f(x,n)=sin(x*n)/n g(x,i)=(i>0)?g(x,i-1)+f(x,i) : 0 set title "sum of sin(x*n)/n" plot for [i=1:7] g(x,i) title sprintf("To %d\n",i) pause -1 # sin(x) のテイラー展開 set xrange [-8:8] set yrange [-2:2] sign(n)=(-1)**n kaijo(n)=gamma(n+1) f(x,n)=sign(n-1)*x**(2*n-1)/(kaijo(2*n-1)) g(x,i)=(i>0)?g(x,i-1)+f(x,i) : 0 set title "Taylor expansion of sin(x)" plot for [i=1:10] g(x,i) title sprintf("To %d\n",i), sin(x) pause -1
一方、現在の CVS 版の gnuplot には evaluate (省略形 eval) というコマンドがあり、 それによって文字列変数を gnuplot コマンドとして実行できます。 もしこれに、set と同様に for 文による iteration 機能があると、 数列や関数列を容易に定義できるように思ったので、 それを実装するパッチを作ってみました。
これを適用すると、以下のようにして数列、関数列を 容易に定義できるようになります:
eval for [i=1:5] sprintf("x%d=1.0/%d",i,i)こちらの方が、再帰的な定義による和よりも自然な方法ではないかと思います。
f0(x)=0
eval for [i=1:5] sprintf("f%d(x)=f%d(x)+x%d*sin(%d*x)",i,i-1,i,i)
前回の報告 (06/05 2008)以後、 現在の CVS 版に入れられた主な機能について紹介します (ChangeLog, manual の更新部分等より)。
5 ヶ月も報告を溜めてしまったので、さすがにたくさんあります。 中でも大きな変更は、以下のものでしょうか。
すでにいくつか (set/unset の for、コマンドラインオプション -e、 emf terminal の enhanced text mode 等) は下にも紹介してあります。
(cf. 「情報やメモ (03/19 2009)」)
gnuplot Q&A 掲示板 での見聞き等で得た情報を備忘録として書いておきます (前回の報告からはだいぶ間が空いてしまっています)。
「情報やメモ (05/20 2008)」 で報告した emf terminal の grid の線種の件はやはりバグで、 現在の CVS 版では修正されています。
(1846 の記事 「re(2): EMF terminal での grid について」)
CentOS 5 に gnuplot-4.2.3 をコンパイルしたんだけど、 x11 terminal が使えない、という質問がありました。
CentOS は RedHat 系の Linux ですが、 最近のクライアント用 Linux は開発環境が (一部分しか) 入ってなかったりするので、 コンパイル済みパッケージをインストールするならともかく、 ソースからフリーソフトをインストールするときは 意外に面倒だったりするようです (うーん、Unix がそれでいいのか ?)。
x11 terminal が使えないのは、configure 時に x11 関係の認識 (ヘッダーファイルやライブラリ) に失敗していることを意味しますので、 それらが適切に指定されていない、あるいはそれらがそのマシンに存在しない、 といったことになっているんだと思います。 元記事の人も、CentOS 5 をフルインストールしてから (フルインストールしたテスト機で) gnuplot-4.3 をインストールしたら ちゃんと x11 terminal が使えるようになったそうです。
(1847 の記事から始まるスレッド 「CentOS5 へのインストール」)
gnuplot の x11 terminal で、linespoints の plot で 点 (points) を白く塗りつぶして点の中に線 (lines) が見えないように したいのですが、という質問がありました。 これに対して、次のような回答がありました。
set pointsize 5
plot 'data' w l lt 1, '' w p lt rgb "white" pt 7, '' w p lt 1 pt 6
set nokey
set view map
set palette gray
set pm3d
set parametric
set urange [0:10]
set vrange [-1:1]
set yrange [-1.1:1.1]
splot u,v*1.1,4 w pm3d, \
u,sin(u),5 w lp lt 1 pt 7 ps 1.6 lw 1,\
u,sin(u),10 w p pt 7 ps 1.2 palette
pause -1
gnuplot*line2Color: whiteと設定し、
set pointsize 5とするなら gnuplot-4.0 でもできる
plot 'data' w l lt 1, '' w p lt 2 pt 7, '' w p lt 1 pt 6
2 つ目のは、松田@東京電機大 さんの超絶技巧で、 実際にやってみるとすごいグラフができます。 最後のはちょっと遅れて思いついたもので、 x11 terminal ならそれなりに真っ当な方法だと思います。
ただ、元記事の方は、最後の方の回答を見る前に、 かなり早い段階で「できないことがわかった」と書いているので、 残念ながらせっかく得られた方法は見ておられない可能性があります。
(1853 の記事から始まるスレッド 「プロットの白抜きについて」)
gnuplot の CVS 版マニュアルの日本語訳の改善 (セクション名の日本語化、doc2tex への対応) が報告されました。
(1863 の記事 「マニュアルセクション名の日本語化」)
媒介変数で複数のグラフを書きたいのですが、という質問がきました。
確かに媒介変数モードだと 2 つの関数を指定することになりますので、 複数のグラフを書けないんではないかと感じるかもしれませんが、 実際は複数指定した関数を単に 2 つずつ関数が使われて行くだけなので、 4 つ関数を指定すれば 2 つのグラフが、 6 つ指定すれば 3 つのグラフが書かれます。例:
set parametric
plot t,sin(t),t,cos(t)
(1865 の記事から始まるスレッド 「媒介変数を使って複数のグラフを書きたいと思っています。」)
pm3d map を使っていて、次の 2 つがわからない、という質問がありました。
1. の方は、zrange だけでなく、cbrange を設定すれば解決します。
2. は、set palette defined, set palette functions 等で実現できます。
set palette defined ( 0 "black", 0.5 "white", 1 "black" )
さらに、PNG ならこれでうまくいくけど、 EPS だとうまくいかない、という追加質問もきましたが、 これは set terminal postscript に color オプションをつければ解決します (デフォルトは monochrome (白黒))。 誤解しがちかもしれませんが、 「白と黒のグラデーション」というのは、 白と黒の 2 値モードである monochrome モードでは実現できません。 途中の灰色を表現するには、多色が利用できる color モードが必要になります。
(1869 の記事から始まるスレッド 「pm3d map の筆問」)
gnuplot のメインの開発者である Ethan Merritt さんと Petr Mikulik さんが、
大阪で開かれる学会 (国際結晶学連合大会) に参加するために来日する、
という連絡が来ました。
日本の gnuplot ユーザと、夕食を共にしながら gnuplot に関する話をしたい
("at some place with beer" ってのが実に魅力的でした)
という話でしたが、
私は残念ながらその時期は事情があり動けなかったので
大阪まで行くことはできませんでした (;_;)
すみませんでした。
どなたか行かれた方がおられましたら、お話をお聞かせ頂きたいと思います。
ところで gnuplot の開発は割と物理系の人が
からんでることが多いと思っていましたが、
「結晶学」の学会ということは Mikulik さん (チェコ)、Merritt さん (米)、
ともに化学系の学者さんなんでしょうか。
gnuplot Q&A の掲示板を主催しておられる
東京電機大の松田さんは多分物理系、
gnuplot の素晴しい解説書を WWW で作っておられるロスアラモス研の
河野さんも多分物理系、
MS-Windows 版 gnuplot や Octave に深く関わっておられる
名古屋大の松岡さんは多分化学系、
そして私は数学屋ですから、色んな分野、色んな国、
そして (多分) 色んな年代の人が関わっていて、
学会などで顔を合わせることはほとんどないような気がしますが
(実際上記の方々には一度も直接会ったことはありません)、
それはインターネットで開発している有益なフリーソフトならではで、
それはそれでとても素晴しいことだと思います。
年齢や風貌もほとんど知らず、
メールなどでしか人柄を伺い知ることはありませんが、
いずれも紳士ですばらしい方々だと思っています。
ということで、今回の件は今でも残念だったと悔やんでいます (T_T)
けど、もうこんな機会はないんでしょうねぇ。
(1876 の記事から始まるスレッド 「gnuplot 開発者が来日」)
異なるデータファイルのデータを描画したい、 例えば a.txt の 1 列目を x 座標とし、 b.txt の 2 列目から c.txt の 3 列目のデータを引き算したものを y 座標としてグラフを書きたいのですが、 という質問がありました。
これは gnuplot 単独ではできませんので、 gnuplot の外でデータを結合してやる必要がありますが、 Unix の paste に相当するものがあれば、
plot '< paste a.txt b.txt c.txt` using ...のようにして、3 つのファイルを行毎に結合したデータを入力し、 それを using 指定で処理する、という手はあります。
元記事の人は MS-Windows 環境だったようですが、 GnuWin32 の TextUtils には paste も入っている、と紹介され、 MS-Windows ならそれを使えばいいそうです。
ただ、「plot '<」の構文を使うには MS-Windows では wgnuplot.exe ではなく、wgnuplot_pipe.exe を使う必要があります。 開発元が配布しているものにはこれも含まれていますが、 角藤さんがコンパイルして公開しているものには含まれていなかったかも、 と書いたら、今後はそれも入れます、と角藤さんからも連絡がきました。 ありがたいことです。
(1901 の記事から始まるスレッド 「別々のファイルにあるデータの差分を描画したい」)
3 種類の点 (point) ○、●、×を使ったグラフを書いていたら、 ×で表示させていたものに○の囲みがついてしまいました (wgnuplot)、 という質問がきました。
私のところでは再現せず、 元記事の人もはじめからやり直したら直りました、という意見が来ました。 gnuplot のグラフは、 terminal やタイミングによっては 前に書いたグラフの要素が残る可能性があります。 特に multiplot などを使うと重ね書きされますので、 そういう可能性は十分にあります。 そういう場合は、 多分 clear や reset というコマンドを使うといいでしょう。
(1907 の記事から始まるスレッド 「ポイント表示について」)
wgnuplot のグラフをクリップボード経由で他のアプリケーションに 貼り付けたとき、 以前の wgnuplot ではうまくいったのに、 新しい wgnuplot (gnuplot-4.2.4、または 9 月以降の CVS 版) では 線の色が消えて灰色になってしまう、という報告がありました。
調べてみると、04/26 辺りの src/win/wgraph.c への変更 (rev.1.58 での変更) でそうなってしまっているようです。
開発元にバグレポートを書いたところ、太字の点線をサポートするために、 今まで CreatePenIndirect() という Win32 API を使っていたのを ExtCreatePen() に変更したが、 それが OS によってはクリップボードで問題を起こしうる、 ということのようでした。 CreatePenIndirect() に戻せばその問題は解消するんだろうけど、 今度は太字の点線が使えなくなってしまうようです。
ただ、皆今忙しくて手をつけられないとか言っていたので、 線幅が 1 の場合には CreatePenIndirect() を使うようにして、 1 より大きい場合は ExtCreatePen() を使うようにすれば 半分位は解消するか、とパッチを送ってみたら、 それが採用されました (されてしまいました)。 元記事の人も、それが採用されたものの角藤版で問題が解消されたようです。
なお、途中で松岡さんも指摘していましたが、 多分 emf terminal 経由で貼り付けるのがより真っ当な解決法だと思います。
(1919 の記事から始まるスレッド 「[Windows]クリップボード経由で図を貼り付けると線の色が消える」)
いくつか、松岡@名古屋大 さんから、 CVS 版に関する情報や MS-Windows 関係の gnuplot に関する情報が投稿されました。
最後のものは、emf terminal で最近 enhanced text mode が 実装されたと私が報告したら、それがどうもうまくいかん、 という報告だったのですが、 どうも MS-Windows native なアプリケーション (MS-Office) ではだめで、 OpenOffice だとちゃんと表示される、というオチだったようです。 その手の話は他にもありました (31 から始まるスレッド 「windows 用の出力」) ので、 まあそういうものなのかもしれません。
(cf. 「情報やメモ (08/14 2009)」)
2 ちゃんねるの掲示板「gnuplot を使おう。その 2」(アドレスは リンクリスト 参照) に書かれた情報について、多少気になるものがありましたので、 少し書いておきます。
splot で y 軸、z 軸を set size square できませんか、 という質問がありました (406)。
y 軸と z 軸の見かけの幅を等しくしたい、ということだと思いますが、 それは視方向 (射影方向) によって変わってしまいますので、 原理的に無理でしょう。 set zrange や set view ,,,<scale_z> の scale_z の値、 set xyplane <frac> (古い版なら set ticslevel) などを調整することで それらしく見えるように調整できるだけでしょう。
wgnuplot を起動するときに、作業ディレクトリを指定できないか、 という質問がありました。 (424)
wgnuplot は 4.2 位から作業ディレクトリに関する仕様が変わりました (cf. 「情報やメモ (10/25 2007)」) ので、 古い wgnuplot から移行した人はそういう需要があるかもしれません。 これについては、以下のようないくつかの解決策が考えられます。
これは、作業ディレクトリが固定している場合に使えます。 wgnuplot はカレントディレクトリの GNUPLOT.INI ファイルに 書かれている gnuplot コマンドを最初に読み込みます (詳しくは help startup 参照)。 よって、その中に
cd 'c:\home\foo\hoge'のように書いておけばディレクトリを自動的に変更してくれます。
現在の CVS 版の gnuplot では -e オプションで 実行時に gnuplot コマンドをコマンドラインから与えられます (cf. 「情報やメモ (10/16 2008)」) よって、
wgnuplot -persist -e "cd 'c:\home\foo\hoge'"のようにすることもできます。
「cd した後で wgnuplot を起動する」ようなバッチファイルを作って それを使うという方法で、これはかなり汎用的な方法です。
もし、作業ディレクトリに移動したい、というのが 「gnuplot スクリプトやデータファイルの置き場所に移動したい」 ということであるならば、 それは cd せずに loadpath を設定することでも実現できます (gnuplot-4.0 以降)。 set loadpath で設定したディレクトリ (複数指定可能) のファイルは ディレクトリをつけなくても load コマンド、 plot コマンド等で読み込めます (help loadpath 参照)。 よって、set loadpath の行を GNUPLOT.INI に入れておけばいいわけです。
なお、set loadpath を設定する代わりに、 環境変数 GNUPLOT_LIB にそのようなディレクトリを設定しておく、 という手もあり、これは loadpath に追加されます。 これなら初期設定ファイルも不要です。
この中でお勧めは、GNUPLOT.INI に set loadpath を設定する方法で、 これを使えば特に cd する必要はないだろうと思います。
友人が「ギニュープロット」と言っていたんだけど、 直してあげた方がいいかなという話がありました (426)。
「直す」という言葉が気になるのですが、以前 「情報やメモ (11/19 2007)」 にも書いたように、 私は gnuplot の「正式な発音の仕方」というものはないと考えています。 「直す」ような「正式な呼び方」というものはなく、 だからわかりやすい読み方をすればそれでいいんじゃないのかな と思っています。
「情報やメモ (10/06 2008)」 に書いた コマンドラインからの -e オプションは、 めでたく開発版に採用されました。 ついでに、-persist オプションは -p でも使えるようになりました。 ただし、wgnuplot では -e は使えますが -p はだめなようで、 相変わらず -persist とする必要はあります (見落し ?)。
「情報やメモ (09/13 2008)」 の、 コマンドラインから gnuplot の内部変数を与えるパッチですが、 本家に投げて議論したところ、以下のような意見が来ました。
ということで、以下のようなパッチにしてみました。
これを適用すると、-e の後ろに awk や perl のように 一行スクリプト形式のように gnuplot 命令を書くことができるようになります:
% gnuplot -persist -e 'set title "test" ; plot sin(x)'まだこれが採用されるかどうかは微妙なところですが、 前のよりはだいぶいいような気がします。
% gnuplot -persist -e 'a=10; s="file.png"' script.gp
gnuplot-4.2.4 がリリースされました。 日本語マニュアル も 後で更新しておきます。 gnuplot-4.2.4 の、gnuplot-4.2.3 以降の機能の更新情報を追加しておきます。
「gnuplot version 4.2.4 での新しい機能、変更、修正」
見たことがないものが多いな、と思ったのですが、 「CVS 版に取り入れられた機能の報告」を、前回 (06/05 2008) から 4 ヶ月近くさぼっています (間隔が前より空いてしまっている) ので、 知らないものが多いのも当然でした <m(_ _)m>
なんとか週末にでも時間を取って、 CVS 版の新しい機能についてまとめたいと思います。
日時データを gnuplot で扱う場合、 gnuplot には "timelevel" という内部仕様があり、 tics のつけ方にやや特徴があります。 例えば、
2008 01 01 50 2008 01 03 25 2008 01 04 30 ....のように各行に年月日と Y の値があるデータに対して、
set xdata time set timefmt "%Y %m %d" set format x "%m/%d" set xtics "2008 01 01", 60*60*24*30 plot 'data' using 1:4 with linespointsのようにすると、xtics は "01/01" から 1 月おき (60*60*24*30 秒 = 30 日) に目盛りが振られますが、これは、 「30 日おき」ではなく、「1 月おき」になっていて、つまり、
01/01, 02/01, 03/01, 04/01, 05/01, ...の目盛りが振られ、正確に 30 日おきの
01/01, 01/31, 03/01, 03/31, 04/30, ...にはなりません。 もちろん通常は前者の方が有用であり、 それなりに reasonable な仕様だとは思います。
日時データ (set xdata time) に 60*60*24*30 (=30 日) おき、 という指定をした場合、実は gnuplot は内部で その tics の進め方の最小単位を「月」にしています。 具体的には、28 日 (60*60*24*28) 以上のインクリメント指定がなされた場合、 x 軸に対する timelevel を TIMELEVEL_MONTHS (月) に設定して、 その timelevel 値を最小単位とし、それ以上のレベルで増やす、 ということをやるわけです。
ところが、現在の gnuplot には逆にそれを解除する方法がありませんので、 正確に「30 日おき」の xtics である
01/01, 01/31, 03/01, 03/31, 04/30, ...をつけることが簡単にはできません。 27 日以下のインクリメント指定ならできるのですが、 28 日以上だとそれができないのはやや不公平に思います。
回避策としては、
set xtics ( "01/01" "2008 01 01",
"01/31" "2008 01 31", ... )
のように手動でいちいち設定するか、CVS 版に取り入れられた set for、
および strptime() (= 日時文字列を秒数に変換する関数) と
strftime() (= 秒数を日時文字列に変換する関数) を使って、
format1 = "%Y %m %d" format2 = "%m/%d" start = strptime(format1,"2008 01 01") end = strptime(format1,"2008 10 01") incr = 60*60*24*30 unset xdata time set xrange [start:end] set for [date=start:end:incr] xtics (strftime(format2,date) date)のようにする手があります (by E.Merritt さん)。 しかし、この方法だと "unset xdata time" しないといけないので、 データ処理を自前でやらなければならず、
format3 = "%4d %02d %02d" three2sec(y,m,d) = strptime(format1,sprintf(format3,y,m,d)) plot 'data' using (three2sec($1,$2,$3)):4 with linespointsのようにする必要があります。 これは、元のものに比べるといかにも面倒です。 28 日を越えた日時に対してはこれだけ面倒になるのはやや不公平なので、 以下のようなパッチを考えました。
これは、set xdata (ydata 等も) の仕様を拡張して以下のようにします。
set xdata {time} {tmlevel {auto|second|minute|hour|day|week|month|year|none}}tmlevel の後ろの指定が timelevel の設定です。 auto の場合は今までと同じでインクリメントの値から自動設定し、 none の場合はその軸は timelevel の仕組みは使用しません。 それ以外はその名前に応じた timelevel の設定です。 これを使えば、
set xdata time tmlevel day set timefmt "%Y %m %d" set format x "%m/%d" set xtics "2008 01 01", 60*60*24*30 plot 'data' using 1:4 with linespointsとするだけで「30 日置き」の xtics が得られることになります。
なお、上のパッチは本家には採用されない可能性も高いので、 自己責任でご利用ください。
gnuplot Q&A 掲示板 で、松田@東京電機大 さんから、 「コマンドラインからデータファイル名を指定できないか」 という話がありました (1893 の記事以下のスレッド 「re(2):xtics for」)。 単一の gnuplot スクリプトで、 複数のデータを連続して処理したい場合などのときに そういうものが指定できると便利なんだけど、 という話でした。
Unix のシェルスクリプトを利用して、 gnuplot スクリプトをシェルのヒアドキュメントとして書いてしまえば それは現在でも実現できるのですが、 MS-Windws 環境などでは確かにあると便利かもしれません。
ただし、gnuplot では一行で複数のデータファイルの描画も可能ですし、 コマンドライン引数のスクリプトとデータを分離するのが面倒です。 ということで、実現の方法としては、以下のような方法が考えられます。
この後者は、スクリプトではデータファイル名を文字列変数としておいて、 その文字列変数をコマンドラインから設定するようにすればいいわけです。 そしてこの後者であれば、実装はそれほど難しくはなさそうだったので、 簡単にテスト版を作ってみました。
これを適用すると、コマンドラインから以下のオプションが使えるようになります。
ただし、このコマンドラインオプションは、 x11 terminal のコマンドラインオプションよりも後に設定する必要がありますし、 対話型で実行する場合は、このオプションの最後に - をつける必要があります。
一応、初期設定ファイル ($HOME/.gnuplot) の読み込みよりも 後で設定しているので、 同名の変数は (型が違っていても) コマンドライン指定の値で上書きできます。
本当は、i,f,s などをつけずに、変数の型を自動判別させたいところですが (gnuplot のユーザ定義変数設定はそれをやっています)、 ちょっとその仕組みに載せるのが面倒そうなのでこのパッチではやっていません。
(cf. 「情報やメモ (10/06 2008)」)
「情報やメモ (09/09 2008)」 の tic の刻みの制御に関する続報です。 xtics で for を利用する場合は、
set xtics (-1)
set for [i=1:4] xtics add (sprintf("[%d]",5-i) 2*i)
のようにする必要があると書きましたが、Merritt さんが
set for [i=1:4] xtics (sprintf("[%d]",5-i) 2*i)
でいけるように改良してくださったようです。
(cf. 「情報やメモ (02/01 2013)」)
「情報やメモ (08/09 2008)」, 「情報やメモ (08/11 2008)」 で報告した、関数を利用した tic の刻みの制御に関する続報です。
本家にそのパッチを送ったところ、さらにそれが改良されて、 「開始値、増分、最終値の制御」の拡張ではなく、 「現在 plot で実装されているのと同様の iteration 機能を xtics に与える」 という形での実装の議論があり、 最終的には iteration 機能を xtics だけでなく すべての set/unset コマンドにも拡張して、 それらで使用できるようにしました (by Merritt さん)。 これはかなり大きな拡張だと思います。 その機能に関するマニュアルの訳を以下につけます。
===== ここから =====例えば set label, set arrow は、CVS 版では with labels, with vectors (と '+') でだいぶ自動的に書けるようにはなっていたのですが、 これを使うとさらにそれが楽に (自然に) 書けるようになると思います。
2 繰り返し (iteration)
`plot`, `splot`, `set`, `unset` コマンドでは、 繰り返し節を使うこともできます。 これは、基本的なコマンドを複数回実行する効果を持ち、 そのおのおのの実行では繰り返し制御変数によって数式は再評価されます。 繰り返し節は現在は以下の 2 つの形式をサポートしています:
例:for [intvar = start:end{:increment}]
for [stringvar in "A B C D"]
さらなる説明については以下参照: `plot iteration`。plot for [filename in "A.dat B.dat C.dat"] filename using 1:2 with lines
plot for [basename in "A B C"] basename.".dat" using 1:2 with lines
set for [i = 1:10] style line i lc rgb "blue"
unset for [tag = 100:200] label tag
===== ここまで =====
ところで、xtics で for を利用する場合は、
set for [i=1:4] xtics (sprintf("[%d]",5-i) 2*i)
とすると、set xtics は前の設定を上書きしてしまいますので、
以下のようにする必要があります。
set xtics (-1)
set for [i=1:4] xtics add (sprintf("[%d]",5-i) 2*i)
一度 xtics をクリア (クリアするためには、今のところ不要なところに
tics を書くしかありません。unset だと一時的に消えるだけです) して、
xtics に add をつけて実行します。
これは、xtics のマニュアル形式の「("label" pos level)」
を利用していることになり、
私が最初に意図した増分形式の拡張とは違う方向での拡張ですが、
私の意図したことはもちろんこれでも行えますし、
この方が考え方も綺麗なのでむしろ喜ぶべき拡張でしょう。
2 ちゃんねるの掲示板「gnuplot を使おう。その 2」(アドレスは リンクリスト 参照) に書かれた情報について、多少気になるものがありましたので、 少し書いておきます。
何本も線を引いたグラフを gnuplot で EPS ファイルにして、 MS-Windows 環境で ghostscript で見る (あるいは LaTeX に貼りつけて dviout で見る) と、 線が 1 本しか出なかったり、ずれて二重の表示になったりする (PDF にしたり印刷には問題はない)、という問題が報告されていました (385)。
gnuplot や ghostscript のバージョンや、 詳しいスクリプトなどが全く紹介されていないので何とも言えませんが、 古い gnuplot (3.7.2 以前) の postscript terminal には、 ghostscript の表示で問題が出る場合がありました。 詳しくは、 「情報やメモ (06/05 2003)」, 「情報やメモ (08/13 2004)」, 「情報やメモ (08/19 2004)」 を参照してください。 ただし、元記事の人の問題がこれに該当するのかはわかりません。
gnuplot で EPS を作って、それを tex と dvipdf で PDF にしていて、 PDF のサイズを小さくするために EPS のサイズを小さくしたいのですが、 という質問がありました (388)。
これも、どのような EPS を使用しているのか、 という情報がないのでなんとも言えませんが、 通常は、gnuplot が生成する EPS は それほど大きいものにはなりませんが、 元のデータ点数が多いと、 それに応じた点をすべて表示しようとするので大きなデータになります。
よって、画像を小さくするには、 データ描画の場合には plot every や外部フィルタなどを使って、 関数描画の場合には set sample などを使って、 解像度に応じてデータ点数を減らす必要があると思います。
しかし、元記事の人は、「小さいグラフを沢山ならべた PDF を作り、 それを PDF ビューワで拡大して細かいところまで見たい」 と言っているので、データ点数を減らせばそれはできないことになります。 「拡大して細かいところまで見る」ということは、 「そのような細かい情報を画像に残す」ということを意味しますから、 それだとそのような PDF ファイルを小さくすることは 多分「原理的に」無理ではないかと思います。
(x,y,z) の点に、f(x,y,z) の値を色で表示する、ということは可能ですか、 という質問がありました (390)。
以前にもこういう質問を見たことがありますが、 現在の gnuplot には点毎に異なる色をつけることができますから、 一応可能です。実際、manual にも以下のような例が見られます:
# 3 次元描画で、各 x,y,z 座標に対応した赤、緑、青の成分を持つ色
# のついた点を配置
rgb(r,g,b) = 65536 * int(r) + 256 * int(g) + int(b)
splot "data" using 1:2:3:(rgb($1,$2,$3)) with points lc rgb variable
ただし、このようなやり方によるグラフが実際に期待したものになるか、 見やすいものになるかというと、必ずしもそうとは言えません。 我々は、図形を見るときは、基本的に 2 次元的にしか見えず、 gnuplot で 3 次元グラフを表示するときも、 ある視点に対する射影である 2 次元面しか見せることはできません。 よって、物体の中身を外から見ることもできませんし、 画面上の点が手前にあるのか奥にあるのかを 区別して見ることも表現することもできません。
例えば、「風呂のお湯の温度分布」の 3 次元データ、 すなわち風呂の中の各 3 次元座標でのお湯の温度のデータが あるとしましょう。 それを上のような形で splot すると、データ点同士ががかなり近い場合、 その with points のグラフは面を構成しますが、 それは「原理的に」風呂の表面の温度分布しか見えず、 風呂の内部の温度分布は表面の色に隠されてしまうはずです。
逆に、そのデータ点同士がそれほど近くはない場合は、 斜めから見ればちゃんと内側の点の色も見えるかもしれませんが、 その中のある点が手前の点なのか奥の点なのかは、 多分かなりわかりにくいだろうと思います。
splot の曲面グラフが 3 次元的に見えるのは、 それが「面」を表すグラフ、つまりその点同士を結ぶ線があって、 それらが小さい格子を形成していて、 それを上下に邪魔する (隠す) ものがないからで、 3 次元の点に色をつけただけの場合は、 点を結ぶ線がないためにどこにあるのかがわからず、 線を書いても上下に邪魔するものがあるために やはり 3 次元的に見ることはかなり難しいでしょう。
線のあるなしで見え方がだいぶ変わる、ということについては、 試しに sin(x+y) などを with dots や with points などで splot してみればわかります。 だから、もっとどのように見たいのか/見せたいのかを ちゃんと具体的に考えるべきだろうと思います。
Z 座標毎にデータを取り出して、それで面を書く、 というサンプルも上げられていますが、 そういうのもひとつの手でしょう。 個人的には、CT スキャンの画像のように、 見たい断面で切った面を表示するのが真っ当ではないかな、 と思います。 風呂の温度分布でも、水平面、あるいは垂直面に切った断面での 温度分布を見せるのが普通でしょう。
例えば天気図などでも、気圧を等圧「線」で表示していますが (gnuplot でいうところの contour)、本来気象現象は 3 次元的で、 高さによっても気圧は変化するはずですが、 それを 2 次元の天気図では表現できないので、 ある一定の高さ、すなわち水平断面での気圧のみを表示しているのです。
また、この f(x,y,z) は基本的にスカラー場と呼ばれるものなのですが、 じゃあベクトル場はどうですか、という質問もあり (395)、 それに対して with vector でできるのでは、という回答もありましたが (397)、 これも上に書いたのと同じことで、確かにできなくはないですが、 そうしたところで期待したものになる、見やすいものになるとは限りません。 ベクトルがたくさん書かれて、どれが手前でどれが奥か、 多分よくわからないものになるでしょう。
2 ちゃんねるの掲示板「gnuplot を使おう。その 2」(アドレスは リンクリスト 参照) に書かれた情報について、多少気になるものがありましたので、 少し書いておきます。
gnuplot は 10**10 以上は認識しないか、という質問がありました (365)。
確かに gnuplot で例えば "print 10**10" とすると
gnuplot> print 10**10 1410065408のように表示されたりします。しかし、これを 10.0**10 とすると
gnuplot> print 10.0**10 10000000000.0と出ます。
10**10 (10 の 10 乗) は、32bit の符号付き整数の範囲 (-2147483648 から 2147483648 まで) を越えています。 10**10 と書くと整数演算になりますが、gnuplot の整数演算は そのマシン (コンパイラ) の整数演算に依存しますので、 32bit 整数計算のマシンでは確かに 10**10 は正しく表示されませんが、 10.0**10 だと実数演算になりますので、 実数演算 (浮動小数演算) なら上のようにちゃんと表示されます。
2 列、数万行あるデータファイル ($1=x, $2=y) を、 0 から 5000 行まで, 5001 から 10000 行までのように 行範囲を指定して描画するには、という質問がありました (372)。
373 に awk を利用する回答が載ったのですが、 それはまあそれなりに真っ当な回答の一つですが、 これは gnuplot だけでも可能で、every を使えば可能です。
plot 'data' every ::0::5000 with lines, \ '' every ::5001::10000 with lines
ところで、その awk に対する回答 (373) に対して、ファイル hoge に
num=num+1
plot " < awk '{if(NR<(num*100) && NR>((num+1)*100))print}'
data"
if(num<100) reread
と書いて animation 表示しようと思ったのですが、
この num が awk に渡らないようです、という質問がありました (374)。
それに対するいくつかの回答はシェル変数の場合と誤解しているようですが、 実はこれは gnuplot で外部プログラムを使用する場合の問題点で、 「gnuplot の内部変数」である num を、 このようにして「plot の引数文字列」内で直接使用することはできません (変数値が展開されません)。 これを解決するには、以下のような方法があります。
1. は、例えば以下のような gnuplot スクリプトを awk などであらかじめ作ることで、ループ変数を使用しない、ということです:
plot " < awk '{if(NR>100 && NR<=200) print}' data" plot " < awk '{if(NR>200 && NR<=300) print}' data" plot " < awk '{if(NR>300 && NR<=400) print}' data" ... plot " < awk '{if(NR>9900 && NR<=10000) print}' data"もちろん、every で
plot "data" every ::101::200 plot "data" every ::201::300 plot "data" every ::301::400 ... plot "data" every ::9901::10000としてもいいでしょう (なお、元記事は不等号の向きがおかしいようです)。 これらはシェルスクリプトや awk で簡単に作ることができますから、 それを gnuplot に食わせればいいわけです。
2. は、
num=num+1
plot "data" every ::(num*100+1)::((num+1)*100)
if(num<100) reread
のようにする方法です。
最後の 3. ですが、 これは上に述べた外部プログラムを利用する問題点を補完する機能で、 gnuplot-4.2 から利用可能になっています。 gnuplot-4.2 では、文字列変数や文字列関数を 文字列が使える多くの場所で使えるようになっていますので、 このような場合にも利用できます。 具体的には、例えば sprintf() 関数を使って以下のようにします:
num=num+1
plot sprintf("< awk '{if(NR>%d*100 &&
NR<=(%d+1)*100) print}' data",num,num)
if(num<100) reread
gnuplot 関数の引数にはもちろん gnuplot 内部変数を渡すことができます。
また、文字列の連結は演算子 . でもできますので、
sprintf() を使わずに以下のようにすることもできます:
num=num+1
plot "< awk '{if(NR>".num."*100 &&
NR<=(".num."+1)*100) print}' data"
if(num<100) reread
ここでは num はその数値文字列として扱われます。
これだと質問者の式にだいぶ近いと思います
(ただし gnuplot-4.2 以降が必要)。
(cf. 「情報やメモ (11/28 2008)」)
「情報やメモ (08/09 2008)」 で報告した、関数を利用した tic の刻みの制御に関する続報です。
多少バグを修正して、
set xtics sn,dn,en,pos(n),label(n)を実装したものを作ってみました。
この画像は、下のスクリプトを処理したものです:
set xtics 1,1,4,(2*n),sprintf("[%d]",5-n) set grid plot sin(x)それなりに使えそうなら、本家に送ってみようと思います。
(cf. 「情報やメモ (09/09 2008)」)
gnuplot で xtics などを使って目盛りの刻みの制御をする場合、 通常は以下の 2 種類の書式を使用します:
後者は自由度は高いのですが、 すべての位置を手動で設定しなければいけません。 前者は多少自動的にやってくれるのですが、 位置や見出しの自由度は低いです。
この後者を使う人も、多くはそれなりの規則性のある位置や 見出しに設定することが多いでしょうから、 むしろこの両者を組み合わせたような設定ができるとよさそうに思います。
現在の CVS 版の gnuplot でも、工夫すれば多少はこれを実現できます。 一つには、以下のように multiplot と xticlabels() を利用することです。 例えば、データファイル 'data' に以下のようになっているとします:
1 1 2 2 ... 9 9これを x 軸の刻みとして使用する例:
set bmargin 2 set grid set xrange [-10:10] set yrange [-1:1] set multiplot # まずは x 軸の刻みなしで sin(x) を出力 unset xtics plot sin(x) # 次に刻みのみを出力 set tics unset key plot 'data' using 1:(2):xtic(2) w p unset multiplot
後者の plot では、y の値が (2) になっていて範囲を越えていますので、 実際には描画されません。しかし、xtic(2) となっているので、 データの 2 列目を見出しとして使用して 1 列目の値のところに刻みをつけていきます。
これは、刻み用のデータを先に作っておく必要がありますが、 csh スクリプトや awk などを利用すれば、 gnuplot スクリプトとその刻みデータを作成する作業は、 一つのスクリプト上で行うことができると思います。
他にも、例えば刻みと見出しを、with vectors と with labels で自作する、 という解決法もあります。ただし、これはだいぶ強引ですし、 set grid には対応しません (それも手動で対応させる、という強引な方法もなくはありませんが)。
ただ、本来はそのような機能を xtics 自身が持てばよさそうに思います。 ということで、現在そのような機能が実装できるかをテスト中で、 まだ色々問題はありますが、そのサンプルを紹介します。
この画像は、下のスクリプトを処理したものです:
set xtics 1,1,9,(n) set grid plot sin(x)この set xtics の設定の仕方は、 上に述べた 2 種類の xtics の利用法のうち、 「開始値、増分、最終値」の方を拡張したもので、
set xtics sn,dn,en,pos(n)のように引数を一つ増やして使います。 この 4 番目の引数 pos(n) があった場合は、 sn, dn, en をパラメータ (仮変数 n) の「開始値、増分、最終値」と見て、 その各 n の値に対して、「pos(n) の場所に刻みを出力する」 という仕様にしています。 上の例では、pos(n)=n なので、1 から 9 までの場所に刻みを作っています。 set grid もこの刻みに従っていることも画像からわかります。
目標は、これをさらに
set xtics sn,dn,en,pos(n),str(n)として、「pos(n) の場所に str(n) の見出しを持つ刻みを出力する」 ということができるようにしたいと思っています (str(n) は 文字列値関数)。 そうすれば、まさに 2 つの形式を組み合わせたようなものに なるのではないかと期待しています。現在の gnuplot (4.2 以降) では、 文字列値関数なるものも作れるようになりましたので、 それを利用すれば十分可能だろうと考えています。
なお、今後徐々に手直ししていって 安定してきたら本家にも送ってみようと思っていますが、 まだまだとりあえずの実装テスト版でかなり問題が多いですので、 上のパッチの利用は今のところはあまりお勧めはいたしません。
2 ちゃんねるの掲示板「gnuplot を使おう。その 2」(アドレスは リンクリスト 参照) に書かれた情報について、多少気になるものがありましたので、 少し書いておきます。
x 軸が時間データであるような場合に、 set format x "%d %B %H:%M:%S" としたら、 plot 時に Bad format character って言われる、という話がありました (341)。
特にフォローはついていないようですが、 これは多分正しい作業をしていない、 あるいは set format 等の役割を誤解しているからだろうと思います。 help time/date を見ればわかると思いますが、 x のデータが時間データである場合、以下のような作業を行うことになります。
"set format" は、 "set xdate time" であるかどうかで制御を変え、 %d, %B などの日付用の書式制御文字が使えるのはその場合だけですから、 最初の "set xdate time" をやらずに "set format" に上のような設定をして描画しようとすると "Bad format character" と言われてしまいます。
ところで、元記事の人は、 元データが "19 Mar 16:59:17" のような形式である、 と言っていますし、 その上で上のような set format x を実行しているようですから、 set format と set timefmt の意味を取り違えている可能性があります。 実際、上のような set format だと、 多分 x 軸の刻みの見出しはえらいことになってしまうでしょう。
set fomat x "%Y-%m" を使っているが、 刻みが多くなると x 軸のラベルが詰まって見難くなる、 という質問がありました (342)。
これもフォローがついていませんが、 これは、set xtics の増分指定に適当な数字を指定して間引くか、 明示的な xtics 指定で解消するといいでしょう。 見出しのない目盛りの刻みを作りたい場合は set mxtics でできます (help set xtics 参照)。
csv ファイルはどうやって開くのか、open では開けない、 という質問がありました (346)。
gnuplot は表計算ソフトではありませんから、 表計算のために csv ファイルを開くことはできません。 wgnuplot に用意されている "open (開く)" というメニューは、 csv ファイルなどを開くためのものではなく、 gnuplot のスクリプトファイルを開くためのものです。
ただし、csv ファイルに書かれているデータを描画させることならできます。 それは plot コマンドの引数として、データを与えればいいのですが、 csv ファイルの場合は、その前に
set datafile separator ","を実行しておくといいでしょう。
gnuplot の起動時に、version 等の表記が表示されるのを抑制するには、 という質問がありました (352)。
gnuplot は、x11 term や win term などの対話型出力形式の実行時には、 最初に "show version" と同じものを表示しているのですが、 この表示を避ける手がないわけではありません。
この、起動時のメッセージ (show version) は、 src/plot.c の main() 内の show_version() で実行されているのですが、 これは「対話型」である場合に実行されることになっていて、 実行時になんらかのオプションがあるとそうではないと見なされて 画面表示はなされないようになります。 よって、実際には「対話型」で立ち上がるようなオプションを付けて実行すれば そこをごまかすことができます。 x11 term, win term の場合はそれぞれ上でそれが可能になるようです。
前回の報告 (04/04 2008)以後、 06/01 2008 現在の CVS 版に入れられた主な機能について紹介します (ChangeLog, manual の更新部分等より)。
およそ 2 ヶ月ぶりの情報なので、まただいぶ色々更新されていて、 いくつか重要な改変もありますが、 今回の目玉は、以下のような感じでしょうか。
rgbalpha は、alpha チャネルをちゃんとちゃんとサポートしているのは 今のところは cairo, gd, x11 のみのようですが、 それなりにおもしろそうです (まだ未確認)。
2 点程報告します。
「情報やメモ (05/20 2008)」 で報告した、emf terminal の grid が実線になってしまう件ですが、 ソースを見たところバグのようでした (grid が点線になるようにしているコードが書いてあるのに それが別なコードで邪魔されている)。 現在の CVS 版では修正されました。
gnuplot の CVS 版を MS-Windows 上で make した (VC++ Toolkit 2003) のですが、 gadgets.c のところでコンパイルが止まってしまいました。 どうやら古いコンパイラのため、という可能性があったので、 VC++ を、以下から無料でインストール可能な VC++ 2005 Express edition に 変えてみました。
なお、VC++ 2005 の方は、これをインストールした後で Microsoft Platform SDK をインストールしないといけないようで、 1GB 以上の容量が必要になりますし、 今まで入っていたものは、Microsoft .NET Framework も含めてアンインストールしないと別のものをインストールできないようです。 同様に、VC++ 2005 と VC++ 2008 を 同時にインストールすることもできないようです。
そして VC++ 2005 でコンパイルしてみたのですが、 やはり同じ箇所でコンパイルが止まってしまいました。 問題の箇所は、最近拡張された set object に対するもので、 そこで構造体の中にある共用体を、 メンバを指定して初期化を行なっているのですが、 gcc ではそれが通るのですが、VC++ (2005) では通りません。 共用体は、C99 からメンバを指定した初期化ができるようになりましたが、 VC++ は C99 には対応していないようです VC++ 2008 も対応していないかもしれません
C89 での共用体の初期化は、最初のメンバへの初期化しか行えないので、 そういう形のコードに書き直せば、コンパイルできます。 例えば以下のパッチで通るようです。
これは、set object に circle や ellipse のサポートが追加された 最近の CVS 版用のものです。少し前のものなら必要ないでしょうし、 また、config.h の EAM_OBJECT の定義をコメントアウトして object を使わないようにすれば、 このパッチがなくてもコンパイルは通ると思います。
なお、VC++ 2005 でコンパイルしたものを実行しようとしたのですが、 MSVCR80.dll がどうとかでて実行できませんでした。 これはコンパイルフラグを変更すればいいようです。 他の警告に対するものを含めて、 現在の config/makefile.nt の CBASEFLAGS
CBASEFLAGS = /G5 /GX /GR /MD /O2 /nologoは以下のように変えるといいようです。
CBASEFLAGS = /EHsc /GR /MT /O2 /nologo
gnuplot Q&A 掲示板 での見聞き等で得た情報を備忘録として書いておきます (前回の報告からはだいぶ間が空いてしまいました)。
なお今回は、その記事の先頭スレッドへのリンクもつけてみました。 よさそうなら、過去のものもさかのぼってそうしておきたいと思います。
実験データを gnuplot に読み込ませたときに、 データが多すぎる、というエラーが出たが、 どれくらいのデータまで読み込めるのか、 という質問がありました。
私自身、だいぶ大きなデータを食わせたことがありますが、 時間はかかるものの、データが多すぎる、 というメッセージが出たことはありません。
実際、gnuplot のソースを見ても、 「データが多すぎる」というエラーメッセージはなくはないのですが、 例えば、gnuplot-4.2.3 では fitting の際に そのようなメッセージが出る可能性はありますが、 それは元記事の splot の際に出るものではありません。
それ以外の "too many ..." というメッセージは、 いずれも直接「データが多すぎる」というものではなく、よってデータが多い、 ということとは別の原因で問題が起きている可能性があります。
ただ、その後質問者からは情報の提供がなく、 結局問題は解決しないままになってしまいました。 しかしそこから派生して、掲示板に、質問に関する注意 (gnuplot のバージョンや OS、エラーメッセージなどを記述すること) を書いたらどうか、という話になり、 さっそくそういう形に改良されました。
(1753 の記事から始まるスレッド 「Linux 版、Windows 版での読み込み可能なデーター容量」)
gnuplot-4.0 で postscript terminal で plus 機能を使うことができますか、 という質問が来ました。
plus 機能とは、以前山賀正人さんが配布していたもので、 gnuplot への追加機能として postscript terminal で LaTeX のような書き方による文字列の記述が可能になるものです (実際には日本語化やヒストリ機能の拡張なども含まれていました)。
ただし、山賀さんが作成しておられたものは、 gnuplot-3.7.2 用のものが最後で、 その後はその山賀さんのものを oden さんが gnuplot-3.8 (開発ベータ版) へ部分的に移植したものを作っておられましたが、 4.0 以降ではそれは利用できないと思っていました。
ところが、松田@東京電機大 さんから、 Vine Linux の gnuplot-4.0 には plus パッチが当たっている、 という情報があり、 調べてみると oden さんの gnuplot-3.8 用のものを 4.0 に移植したものが 使われているようでした。
元記事の方は MS-Windows ということだったので、 その Vine Linux 用のパッチを取得して、 MS-Windows 上で make してみたのですが、 一応それなりに plus 機能を使えるものが作れるようです。 ただし、コンパイルする環境とパッチ当ての作業、 makefile の修正等が必要なので、 そういった知識がないとその wgnuplot を build するのは難しいと思います。
ところで、その plus パッチを 4.2 以降、 あるいは 4.3 (CVS 版) に移植できるかどうかですが、 4.0 と 4.2 では postscript terminal の構造がだいぶ変わりましたので、 可能かどうかわかりません。少なくとも簡単ではないと思います。 なお、元々の plus パッチには X11 terminal の日本語化 (日本語フォントの指定) なども含まれているのですが、 これは既に 4.2 以降には取り込まれています。
(1757 の記事から始まるスレッド 「version 4.0 について」)
ylabel の位置を変更したいのだけど、どうもうまくいかない、 という質問がありました。
ylabel には offset を指定することができますが、 これは gnuplot-4.2 から少し変更されていて、gnuplot-4.0 では
set ylabel "hoge hoge" 3, 5 # 3 文字分右に、5 文字分上にという形式だったのですが、それが現在は
set ylabel "hoge hoge" offset 3, 5のように変わっています。offset 指定の座標系を選択することもできますし、 splot の場合は 3 つの座標の組で指定することもできるようになっています。
ところで、gnuplot のマニュアルに、フォント指定は
font "<font>{,<size>}"のように書かれているのを見て、元記事の人は
font "Times-New-Roman{,32}"のように書いておられたのですが、このマニュアルの { } は、 省略可能なオプションを示すための書き方で、{ } はつけずに、
font "Times-New-Roman"のどちらかのように書く、ということを意味するための記法です。 ただ、確かに初心者は間違ってそのように読んでしまう 可能性は十分あるように感じました。
font "Times-New-Roman,32"
(1766 の記事から始まるスレッド 「eps出力時の描画位置」)
松岡@名古屋大 さんから SVG に関する情報の提供がありました。 私も、以前うちの研究室の卒研との関係で多少調べたことがあるので、 その情報を上げておきました。
SVG はそれなりにいい点が色々あるので、 メジャーなブラウザで直接表示できるようになるとはやるかなと思うのですが、 MS-IE がなかなか対応してくれないので、 広がりはイマイチな気がします。
(1771 の記事から始まるスレッド 「SVG について」)
gnuplot のインターフェースの改善のために、 GUI で操作するようなフロントエンドを作成したい、 という意見がありました。
現在もそういうソフトはいくつかあって、 例えば以下のようなものが紹介されました:
tkgnuplot, UniGNUPlot, Qgfe, RubyPlot結局元記事の人は、自分でそのようなものを作る方向で、 Tcl/Tk (MS-Windows) でのプログラミングを始めたようです。 もしよさそうなものができたら、是非公開してもらいたいと思います。
(1775 の記事から始まるスレッド 「インターフェースに関してです」)
いくつか、松岡@名古屋大 さんから、 CVS 版に関する情報や MS-Windows 関係の gnuplot に関する情報が投稿されました。
松岡さんは、Octave (グラフ描画の際に gnuplot を内部で使用する) というソフトに深く関わっていて、 そちらの方でも精力的に活動しておられるようで、 そういう方向から、gnuplot の開発元にも色んな意見を出しておられます。 今後ますますの活躍が期待されます。
grid を表示させると、通常の terminal では点線になるのに、 emf terminal では実線になってしまう、という質問がありました。
調べてみると、emf terminal では 確かに線種 0 が実線になっているためにそのようになります (grid のデフォルトの線種は 0)。 よって、test の結果を見て、適当に点線を選べばその問題は回避できます。 color dashed の場合は、38 辺りが黒の点線になっているようなので、
set grid lt 38で黒の点線になります。
ただ、線種 0 が実線になっている理由はよくわかりません。 もしかするとバグかもしれません。
(1803 の記事から始まるスレッド 「EMF terminal での grid について」)
MS-Windows 上で、VC6.0 で ShellExcute を用いて wgnuplot を起動させている場合に、 graph ウィンドウを閉じることで 本体の gnuplot ウィンドウ (コマンドウィンドウ) も閉じるようにできないか、 という質問がありました。
これに対して、松岡@名古屋大 さんから、 コマンドウィンドウを最初から立ち上げなければいいのではないか、 '-persist' をやめて、最後に '-' をつけることでそれは可能である、 といった回答がありました。 多少裏技っぽいのですが、有用なワザですね。
(1808 の記事から始まるスレッド 「一括で終了させる方法はありませんか」)
Ubuntu Linux 上で UTF-8 ロカールを使用しているが、 x11 terminal, postscript terminal の日本語が文字化けしてしまう、という質問ありました。
EUC-JP エンコーディングならうまくいくようなので、 UTF-8 ロカールの環境がうまく設定されていないのではないかということで、 元記事の方が調べたところ、gs (8.61) の設定 (CJK 対応をインストールした後の reconfigure) をしていなかったため、 ということで postscript terminal の方は解決したようです。
なお、個人的には x11 terminal の文字化けも気になるのですが、 そちらの方は残念ながらその後の情報は得られず、 解決したのかどうかもわかりませんでした。
(1813 の記事から始まるスレッド 「eps への日本語出力が文字化けする」)
3 つ以上の y 軸を用いてグラフを書きたい、という質問がありました。
これに対して、以下のような回答がありました。
(1824 の記事から始まるスレッド 「3 つ以上の Y 軸を用いてグラフを書きたい」)
MS-Windows の wgnuplot で、 グラフウィンドウのウィンドウタイトル (default では "graph window") を変更できないか、 という質問がありました。
これに対して、以下のような回答がありました。
ところで、少し調べてみたら、ウィンドウのタイトルの変更は、 Win32 API というものの SetWindowText() とかいう関数でできるらしいので、 少しいじってみたらなんとかできました。 残念ながら、CVS 版はうまくコンパイルできなかったのですが、 4.0 用のパッチを本家に送って無事採用してもらいました (松岡さんにもだいぶフォローしてもらいました)。 よって、現在の CVS 版の wgnuplot なら、 「set term win title "hoge"」 でグラフウィンドウのタイトルを変更できます。
(1827 の記事から始まるスレッド 「ウィンドウタイトル」)
(cf. 「情報やメモ (05/22 2008)」, 「情報やメモ (10/16 2008; no.3)」, 「情報やメモ (02/26 2009)」)
前回の報告 (01/25 2008)以後、 現在の CVS 版に入れられた主な機能について紹介します (ChangeLog, manual の更新部分等より)。
前回の報告からだいぶ間があいたので、色々な改良が行われていますが、 ざっと見て大きな変更は、以下のような感じでしょうか。
with circles に関しては、 既にバブルチャートに関して紹介している通りです。
また、with circles とともに set obect circle が実装され、 これは扇形が描けますので、 circles.dem を見るとわかりますが、 これで円グラフを実現することができます。 しかし、gnuplot 内でデータから直接円グラフを描く、 ということが簡単にできるわけではなく、 awk などでデータから set object circle の列を出力する必要はあります。
そのうちに、 「情報やメモ (02/08 2005)」, 「情報やメモ (02/12 2005)」 で紹介した円グラフの描画用 awk スクリプトを、 set object circle を使うものに書き換えたものを作ってみようかと思います。
「情報やメモ (03/15 2008)」, 「情報やメモ (03/13 2008)」, 「情報やメモ (01/28 2008)」 で取り上げてきたバブルチャートの件ですが、 現在の CVS 版での例を紹介します。
使用したデータは、 「情報やメモ (01/28 2008)」 と同じもので、基本的に以下のようなスクリプトで実行しています。
set clip pointsつまり、「情報やメモ (03/13 2008)」 で紹介した簡単な方法で書いたものです。 2 つ目の plot は sort を使ってデータの 3 列目、 すなわち半径の大きいものが先に来るようにしていて、 大きい円が下 (奥) になるようにしています。
set xrange [0:6]
set yrange [0:6]
scale = 0.3
plot 'data' using 1:2:($3*scale) with circles lt 1 fs solid border -1
pause -1
plot '< sort +2 -3 -n -r data' using 1:2:($3*scale) with circles \
lt 1 fs solid border -1
前の points 6, 7 を用いる方法では、 terminal によって円の大きさが変わってしまうという欠点がありましたが、 with circles ではそれはありません。 よって、これでだいぶ簡単にバブルチャートが描けるようになったわけです。
しかし、残念ながらいずれも描画領域でのクリッピングがされていません。 少なくとも post terminal では set clip point でクリッピングされるはずだ、 と聞いたと 「情報やメモ (03/15 2008)」 に書きましたが、 実際にはそうなっていないようです。 よってそれに関しては、今のところは 「情報やメモ (01/28 2008)」 のような重ね書きによる対処が必要なようです。
(cf. 「情報やメモ (05/07 2010)」)
「情報やメモ (03/13 2008)」 で、 最近 CVS 版 gnuplot で実装された "with circles" ではバブルチャートのグラフを描く場合に問題がある、 という話を書きましたが、 これに関して以下のような話を開発者に報告してみました。
後者は、その方が例えば "set object circle" の挙動とも合いますし、 そのような仕様になっていれば、むしろ現在の挙動は、
plot 'data' with circles lt 1 fs solid noborder, \のように、内部と境界を別々に描画することで簡単に再現できるからです。
'' with circles fs empty border -1
すると、クリッピングに関しては terminal 依存の問題らしく、 現在 PostScript, PDF, SVG 出力に関しては修正されているそうですが、 すべての terminal で統一的に修正することはできないだろう、 という話でした。
また、内部と円周の描画順序については、 そのような挙動になるような差分 (src/graphics.c の plot_circles() への) も送ったのですが、どうやらそれが採用されたようですので、 最新の CVS 版ではどうやら多少は簡単に with circles でバブルチャートが描けるようになったようです (まだ動作は未確認です)。 ただ、まだクリッピングの問題がありますので、 「情報やメモ (01/28 2008)」 で紹介したような、rectangle を multiplot で重ね書きするような対処は必要になるかもしれません。
「情報やメモ (01/28 2008)」 で「バブルチャート」(各 x,y での値を円の大きさで表す平面上の 3 次元グラフ) を point (pointtype 6, 7) で書く、という手を紹介しましたが、 その後 (タイミング良く ?) CVS 版 gnuplot (4.3) で "with circles" や "set object circle" が実装されました。
"with circles" は、まさに指定した場所に円を書くためのもので、 x,y,r と 3 列のデータから、中心 (x,y)、半径 r の円を書きます。 以下、日本語ヘルプから引用:
スタイル `circles` は、各データ点に明示された半径の円を描画します。 これは、x, y, 半径、の 3 列のデータが必要です。 4 列目のデータを追加して色の情報の指定とすることもできます。 半径は、常に描画の水平軸 (x または x2) の単位で解釈されます。 y 方向の縮尺と描画のアスペクト比は、いずれも無視されます。上のサンプルを見てわかる通り、 円は塗り潰しの指定や円周の線種の指定なども行えるので、 まさにバブルチャートが書けるか、と思ったのですが、 実は 「情報やメモ (01/28 2008)」 のようなグラフが手軽に書けるようになっているかというと 実はそうではないようで、問題点が 2 つあります。
例 (面積が 3 列目の値に比例するような円を描画):plot 'data' using 1:2:(sqrt($3)) with circles fillstyle emptyこれは、pointstyle 6 で点のサイズを variable とした `points` による描画と似ていますが、 circles は x 軸の範囲で縮尺される点が異なります。
前者のクリッピングの問題は、多分バグではないかと思うのですが、 まだよく調べていません。 後者の方は、「情報やメモ (01/28 2008)」 では、大きな円を先に書いて、小さな円を後に書くことで、 小さな円が上に載って、 それが下の大きな円の一部を隠すように描いていましたが、 それができません。 イメージとしては、
plot 'data' using 1:2:3 with circles lt 1 fs solid border -1のようなことをすれば、
1 番目のデータ点の円内部を描いてその円周を描く、のように描いてくれるものかなと思って、それなら 「情報やメモ (01/28 2008)」 のようになるかなと思ったのですが、 実際にやってみるとすべての円の円周が、 円内部の塗り潰しには隠されずに表に出ています。 つまり、重ね描きのイメージとしては
2 番目のデータ点の円内部を描いてその円周を描く、
...
1 番目のデータ点の円内部を描く、のようなことをやっているように見えます。 後のデータに対する円の内部が、 前のデータの線を消すようにできればいいのですが、 それが今のところはできないようなので、 「情報やメモ (01/28 2008)」 のような図を描くには、 結局 1 点毎の描画、つまり for を使って、
2 番目のデータ点の円内部を描く、
...
1 番目のデータ点の円周を描く、
2 番目のデータ点の円周を描く、
...
plot for [i=1:N] 'data' using 1:2:3 every ::(i-1)::(i-1) \のようなことをやらないといけないようです (これならちゃんと後のが前のを隠してくれます)。
with circles lt 1 fs solid border -1
(cf. 「情報やメモ (03/15 2008)」, 「情報やメモ (04/03 2008)」, 「情報やメモ (05/07 2010)」)
gnuplot Q&A 掲示板 で松岡さんに教えてもらいましたが、gnuplot-4.2.3 がリリースされました。 日本語マニュアル も更新いたしました。
「情報やメモ (09/05 2007)」 で、 gnuplot-4.2.2 以降の機能の更新情報を紹介しましたが、 ここで gnuplot-4.2.3 の、gnuplot-4.2.2 以降の機能の更新情報を 追加しておきます。 これは、gnuplot の配布物に含まれるファイル NEWS の訳です。
「gnuplot version 4.2.3 での新しい機能、変更、修正」
「情報やメモ (02/13 2008)」 の SVG のテストで、 xsvg, svg2png の出力では回転されている文字列の色が 緑に変わっていませんでしたが、 これは libsvg-0.1.4 のバグであることがわかりました。 それを修正すれば、正しく緑に表示されます。 詳しくは、 「Unix に関するメモ (02/19 2008」 をご覧ください。
また、svg.trm はまた最近更新されました。 それに対応して use タグを使わないパッチも更新してみたのですが、 今度はその新しいタグオプションの書き方に ImageMagick (6.2.4) が対応していないらしく、 display では以前よりも描画できない要素が増えてしまいました。 最近の ImageMagick ではどうかわかりませんが、 とにかく ImageMagick の対応を待つ方がよさそうです。
「情報やメモ (02/13 2008)」 の SVG のテストの最後に、
「情報やメモ (11/12 2004)」 で紹介した use タグを使わないパッチは使っていません。 それを使うと、もしかすると多少結果が変わるかもしれません。と書きましたが、実際に試してみると変わりはないようです。 ところで、そのパッチは以前は公開していませんでしたので、 ついでにバグも修正したものをとりあえず以下に置いておきます。
これは CVS 版 gnuplot の term/svg.trm (rev. 1.88) への差分で、 このパッチを当てると、 svg terminal で追加オプション nousetag が指定できるようになり、 これを指定すると use タグを使用しない SVG 画像が生成されます。 そのような SVG ファイルは、不十分ですが ImageMagick の display でも見ることができるようになります。
参考のため、 このパッチを当てた場合の、nousetag オプションを使用した場合と 使用しなかった場合の test コマンドの出力を以下に置きます。
gnuplot Q&A 掲示板 で、少し SVG 形式に関する話題が出ました (1771 番の記事 「SVG について」)。 最近は、SVG を扱える環境も以前に比べると だいぶよくなっているのではないかと思い少し調べてみましたので、 ここに少しまとめておきます。
現在 Unix 上で SVG ファイルを参照するには、 「情報やメモ (11/12 2004)」 で紹介した ImageMagick (display) や batik の squiggle 以外にも、 inkscape, xsvg, svg2png などがあります。 「情報やメモ (11/12 2004)」 では ImageMagick と squiggle の表示画面を紹介してありますが、 ここではそれに加えて inkscape, xsvg, svg2png の出力を紹介します。 まずは、gnuplot の test コマンドの SVG 出力に対する 画面表示等を比較します。
xsvg, svg2png は、ともに libsvg, libsvg-cairo を利用する、 cairographics.org の 応用ソフトなので、表示もほとんど同じです。 ともに、ボックスの pattern fill、 多角形の塗り潰しができていないことがわかります。 また、よく見ると回転されている文字列の色が変わっていません (正しくは緑で表示されるはず)。 inkscape は、多角形の塗り潰しはいいのですが、 ボックスの pattern fill が一部うまくいっていません。
次は、日本語のテストを行います。 簡単に以下のようにして作成した SVG ファイルを利用しました。
#! /bin/csh -f nkf -w <<EOF | gnuplot set term svg set out 'test2.svg' set title "テスト" font "HG-MinchoL" set xlabel "テスト" font "Ryumin-Light" plot sin(x) set out EOF"HG-MinchoL" は、テストに使用した環境 (Solaris 9) では fontconfig で利用できるフォント名ですが、 "Ryumin-Light" はそうではありません。 そのそれぞれのフォントを指定して title と xlabel を書いて sin(x) のグラフを書いたものを、nkf で UTF-8 にコード変換したものです。 こちらは、ついでに squiggle (batik) による表示も一緒に示します。
見てもらうとわかりますが、 xsvg, svg2png, inkscape はいずれも title の方の "HG-MinchoL" の方は そのフォントで表示されているようですが、 xlabel の方の "Ryumin-Light" の方は なんとなくそのフォントではなく、代用フォントで表示されているようです。 これは、inkscape も含めて fontconfig に対応したツールなので そのようになっているのだと思われます。
一方 squiggle の方は、日本語はいずれも出ていますが、 フォントは、なんとなく "HG-MinchoL" も "Ryumin-Light" も使われていなくて、 いずれも別なフォントが使われているように見えます。 squiggle は fontconfig ではなく Java によるツールなので、 そちらの日本語対応で処理されているためだと思います。
結果としては、今回試したツールでは以下のような感じです。
なお、今回は 「情報やメモ (11/12 2004)」 で紹介した use タグを使わないパッチは使っていません。 それを使うと、もしかすると多少結果が変わるかもしれません。
2 ちゃんねるの掲示板「gnuplot を使おう。その 2」(アドレスは リンクリスト 参照) に書かれた情報について、多少気になるものがありましたので、 少し書いておきます。
gnuplot を立ち上げる度に設定ファイルをロードするのが面倒なんですが、 という質問がありました (319)。
これは、help startup を参照すればわかりますが、 gnuplot は、Unix では .gnuplot という名前、 MS-Windows では GNUPLOT.INI という名前の初期設定ファイルが カレントディレクトリにあればそれをまず読み込みます。 カレントディレクトリになくてもホームディレクトリ (MS-Windows の場合は環境変数 GNUPLOT の値のディレクトリ) にそれがあれば、それを読み込みます。
tan(y)+e^(-y)=x のグラフを書くには、という質問がありました (323)。
これは、陰関数というよりは y=tan(x)+exp(-x) の逆関数のようなもの (正確には、これは単調ではないので逆関数はありません) なので、x 軸と y 軸を入れかえたグラフが書ければいいのですが、 gnuplot では x 軸と y 軸を入れかえてグラフを書くことはできません。
ヒントとも少し来ていたのですが、そのようなグラフを書くには、 例えば次のような 2 つの方法があります:
前者は、この曲線をパラメータ表示にして、 (x,y)=(tan(t)+exp(-t),t) という曲線を書けばいいわけです。
後者は、table terminal (gnuplot-4.2 以降は set table) を利用して、 y=tan(x)+exp(-x) のグラフの点データ ((x,y) のデータ) を一度ファイルに保存し、 そのデータを using 2:1 (x,y の入れ替え) で書く、という方法です。
データの 3 列目と 4 列目の文字列を連結するには、 という質問がありました (329)。
gnuplot-4.2 以降では、 例えば with labels でデータ内の文字列を列データとして取得して グラフ上に表示できるようになりましたが、 「using 1:2:3 with labels」だとうまくいくのに、 「using 1:2:sprintf("%s+%s",$3,$4) with labels」 がうまくいかない、という話のようです。
これは、どううまくいかないかというと、 以下のようなエラーメッセージが表示されます:
f_sprintf: attempt to print numeric value with string formatこれは、ここに書かれている通りで、 「$3,$4 は数値なので、それを sprintf の %s に指定することはできない」 という意味です。つまり、gnuplot には
「awk や perl などのように文字列と数値の変換を 文脈にしたがって自動的に行う」という機能はなく、文字列は文字列として、 数値は数値として取得して使用しなければいけません。 "with labels" の場合の "using 1:2:3" だけは 例外的に 3 列目を文字列として扱うようになっています。
データから列のデータ値を取得する場合、 $1 や column(1) は数値として扱われますが、 文字列を文字列値として取得する場合には stringcolumn() (またはその省略形の strcol()) を使用します。 よって、これは、
using 1:2:(sprintf("%s+%s"strcol(3),strcol(4))) with labelsとすればうまくいったわけです。
なお、この例では sprintf() 全体をカッコでくくっていますが、 using 指定子に式を書く場合は ( ) でくくらなければいけませんので、 元の質問者の例はそれに関しても修正が必要になります。 また、文字列の連結には '.' という演算子が使えるので、
using 1:2:(strcol(3) . "+" . strcol(4)) with labelsでも同じ結果が得られます。
なお、awk で処理したら、という意見もあったようですが、 元の質問者のデータには 3 列目にスペースが入ることがあったりなかったりするようなので、 この場合は awk での処理の方が難しそうです。 gnuplot なら " " で囲んである文字列内にスペースがあっても、 囲んである部分を一つの文字列として適切に処理してくれます。
最近大学では授業改善用の授業アンケートがはやっていて、 いわゆる「レーダーチャート」なるものを見る機会が増えています。 はて、これは gnuplot で書けるんかいなと思ってやってみましたので、 ここにまとめておきます。
レーダーチャートとは、中心から項目数分の動径を角度等間隔に書き、 それを各項目毎の軸として値を取り、 それを線で結んで多角形としたものです。 gnuplot の極座標モードを使えば簡単にできるのかなと思ったのですが、 それなりに作業が必要なようです。 まず、描画するデータは以下のような形式であるとします:
生徒 国語 社会 理科 算数 英語これを各生徒毎に描画するのですが、 本来 gnuplot のデータとしては縦横逆の形式の方が都合がいいのですが、 生徒のデータを順に追加していく、ということを考えると、 むしろ上のデータ形式の方が自然だと思いますので、 ここから出発することにします。
Aさん 70 80 60 50 90
Bさん 40 20 90 90 70
Cさん 90 90 90 90 90
まず、これを gnuplot にかける前に、 以下の点でデータを前処理する必要があります:
データの処理には awk (gawk) を利用します。 awk スクリプトと gnuplot スクリプトが分離すると管理が面倒なので、 例えば 1 つの csh スクリプト内に両者を書けばいいでしょう。 csh スクリプト内に awk のスクリプトを書く場合は、 行末に '\' を入れて csh スクリプトの継続行とすること、 エスケープする必要のある特別な記号 (! など) は '\' でエスケープすることに注意してください:
#!/bin/csh -f awk 'BEGIN{dnum=-1}\ (\!/^#/ && NF>1){\ if(dnum<0){ N=NF; for(j=2;j<=N;j++) kamoku[j]=$j; dnum=0; next }\ else if(N!=NF){ errorexit=1; exit }\ else{\ name[++dnum]=$1; \ for(j=2;j<=N;j++){ point[dnum , j]=$j; mean[j]+=$j }\ }\ }END{ if(errorexit || dnum<=0 || N==0){ print "Error."; exit }\ for(j=2;j<=N;j++) mean[j]/=dnum;\ printf "科目";\ for(j=1;j<=dnum;j++) printf(" \"%s\"",name[j]);\ print " \"平均\"";\ for(j=2;j<=N;j++){\ printf "\"%s\"",kamoku[j];\ for(k=1;k<=dnum;k++) printf " %s",point[k , j];\ printf " %f\n",mean[j];\ }\ printf "----";\ for(k=1;k<=dnum;k++) printf " %s",point[k , 2];\ printf " %f\n",mean[2];\ }' data > tmpf1ここでは、データファイルは '#' で始まる行や空行は無視するようにしています。 この awk 処理によって、 データファイル data は 次のような一時ファイル tmpf1 に変わります:
科目 "Aさん" "Bさん" "Cさん" "平均"この第 2 から最終フィールドまでを、 極座標モードで with linespoints で書けばいいのですが、 極座標モードでは、データは「偏角」と「原点からの距離の組」になります。 上の 5 つのデータに対しては、角度は、 例えば 12 時の角度から反時計回りに 360/5=72 度ずつ進めて、
"国語" 70 40 90 66.666667
"社会" 80 20 90 63.333333
"理科" 60 90 90 80.000000
"算数" 50 90 90 76.666667
"英語" 90 70 90 83.333333
---- 70 40 90 66.666667
90 度、90+72 度、90+144 度、90+216 度、90+288 度の位置に書く必要があります。これは、例えば以下のようにすればいいでしょう:
set polarset size square は描画グラフを正方形にし、 set angle degree で偏角の単位を度にしています。 また、using の後ろの title column(2) は、 gnuplot-4.2 から導入されている using title の機能で、 これにより、1 行目の 2 列目の値をその描画の title として使用し、 key の説明にそれが使われます。 上のデータでは「Aさん」という文字列がそれになります。
set size square
set angle degree
# N = 項目の数
pos(j,N) = 90 + j*360/N # j 番目の項目の偏角
plot 'tmpf1' using (pos($0,N)):2 title column(2) w lp
とりあえず、これを人数分やればいいわけですので、 CVS 版 gnuplot (4.3) の iteration を使えば、以下のようにできます:
set polar
set size square
unset tics
set angle degree
set xrange [-120:120]
set yrange [-120:120]
N = system("cat tmpf1 | wc -l") -2
M = system("awk '{print NF; exit}' tmpf1") -2
# N = 項目の数
# M = 人数
pos(j,N) = 90 + j*360/N # j 番目の項目の偏角
plot for [i=2:M+1] 'tmpf1' using (pos($0,N)):i title column(i) w lp pt 2+i, \
'' using (pos($0,N)):($(M+2)) title column(M+2) w lp pt 0 lt -1
N,M は system() を利用してデータ tmpf1 から取得しています。 N は (tmpf1 の行数) - 2、M は (tmpf1 のフィールド数) - 2 としています。 plot は、最初の for の部分で各学生のデータを、 次の行の plot で平均値を出力しています。 なお、この gnuplot スクリプトを csh スクリプトのヒアドキュメントに書く場合、 "$0" は "column(0)" に、 "$(M+2)" は "column(M+2)" に変える必要があります。
ただ、上の画像を見るとかなり味気ないレーダーチャートですし、 各グラフの値がどれくらいなのかがわかりません。 今度はそれを重ねて書いてみることを考えてみます。
まずは、背景に各項目毎の動径と、グリッド代わりの同心正多角形を書いてみます。 動径は set arrow で書きますが、 これは iteration のようにループを用いて簡単に書くことができず、 一つ一つ書いていかないといけません。 よって、csh スクリプトのループを用いて gnuplot サブスクリプトを生成し、 それを gnuplot で load することにしましょう。
#!/bin/csh -f @ N = `cat tmpf1 | wc -l` - 2 @ M = `awk '{print NF; exit}' tmpf1` - 2 # N = 科目数、M = 人数 set maxpoint = 100 # 最高点 set j = 0 echo '' > tmpf2 while ( $j < $N ) @ k = $j + 1 echo "r1=$maxpoint" >> tmpf2 echo "a1=pos($j,$N)" >> tmpf2 echo "set arrow $k from 0,0 to r1*cos(a1),r1*sin(a1) lt 0 nohead" >> tmpf2 @ j ++ endN, M は gnuplot 内と同じ方法でデータから取得しています。 作成する gnuplot サブスクリプトである tmpf2 は、 上の gnuplot スクリプトで作成した関数 pos() を使用することにしていますので、 tmpf2 を実際に読み込む場合は、pos() を定義した後に読み込む必要があります。 また、各 arrow のタグを $k ($j + 1) としていますが、 これは gnuplot のタグは正の数字でないといけないためです。 これを load すれば点線 (lt 0) の動径が描画されます。
次はグリッド代わりの正多角形ですが、これは arrow で書くのは面倒なので、 plot で定数値を書かせることで描画すればいいでしょう。 よって、前の plot に以下のように追加すれば、 点線のグリッド正多角形が追加されます:
maxpoint = 100 # 最高点
divide = 5 # 刻みの分割数
plot for ... ,\
for [i=1:divide] '' using (pos($0,N)):(i*maxpoint/divide) \
w lp notitle ps 1 pt 0 lt 0
最後に、各動径と各グリッド正多角形にラベルをつけます。 各動径には科目名を、グリッド正多角形には点数をつけますが、 科目名の方は、with labels で描画すればいいでしょう。 グリッド正多角形の方は、 divide と関係した個数の描画になるので、 これはむしろ arrow と同じサブスクリプトの中で、 set label で設定してやることにします。 科目名の方の plot の追加部分は以下の通りです:
# maxpoint = 100 # 最高点各動径方向の 100 点の少し外 (maxpoint+10) の場所に、 2 行目から N 行目まで (平均点まで) の 1 列目の文字列 (=科目名) を with labels で出力しています。
# N = 5 # 科目数
plot for ...\
'' using (pos($0,N)):(maxpoint+10):1 every ::1::N with labels notitle
次は、set label によるグリッド正多角形のラベルの、 前の set arrow に対する追加部分:
set maxpoint = 100 # 最高点 set divide 5 # 刻みの分割数 set j = 0 while ( $j <= $divide ) @ k = $j + 100 echo "y=$j*$maxpoint/$divide" >> tmpf2 echo "set label $k sprintf('%d',y) at 0,y offset .5,0" >> tmpf2 @ j ++ endタグは、前のタグとぶつからないように大きな数字にしてあります ($j+100)。
以上を一つの csh スクリプトにすると、以下のようになります。
#!/bin/csh -f ### 各種設定 set data = data set tmpf1 = tmpf1 set tmpf2 = tmpf2 setenv GDFONTPATH /usr/local/share/fonts/ttf set image = radar.gif # gif 画像ファイル名 set gif = 1 # 1 なら gif 画像を作成、0 なら x11 terminal set maxpoint = 100 # 最高点 set divide = 5 # 刻みの分割数 set margin = 20 # グラフの余白 run1: ### awk で前処理 awk 'BEGIN{dnum=-1}\ (\!/^#/ && NF>1){\ if(dnum<0){ N=NF; for(j=2;j<=N;j++) kamoku[j]=$j; dnum=0; next }\ else if(N!=NF){ errorexit=1; exit }\ else{\ name[++dnum]=$1; \ for(j=2;j<=N;j++){ point[dnum , j]=$j; mean[j]+=$j }\ }\ }END{ if(errorexit || dnum<=0 || N==0) exit; \ for(j=2;j<=N;j++) mean[j]/=dnum;\ printf "科目";\ for(j=1;j<=dnum;j++) printf(" \"%s\"",name[j]);\ print " \"平均\"";\ for(j=2;j<=N;j++){\ printf "\"%s\"",kamoku[j];\ for(k=1;k<=dnum;k++) printf " %s",point[k , j];\ printf " %f\n",mean[j];\ }\ printf "----";\ for(k=1;k<=dnum;k++) printf " %s",point[k , 2];\ printf " %f\n",mean[2];\ }' $data > $tmpf1 if ( -z $tmpf1 ) exit run2: ### サブスクリプトの作成 # N = 科目数、M = 人数 @ N = `cat $tmpf1 | wc -l` - 2 @ M = `awk '{print NF; exit}' $tmpf1` - 2 # 動径 set j = 0 echo '' > $tmpf2 while ( $j < $N ) @ k = $j + 1 echo "r1=$maxpoint" >> $tmpf2 echo "a1=pos($j,$N)" >> $tmpf2 echo "set arrow $k from 0,0 to r1*cos(a1),r1*sin(a1) lt 0 nohead" >> $tmpf2 @ j ++ end # グリッド正多角形のラベル set j = 0 while ( $j <= $divide ) @ k = $j + 100 echo "y=$j*$maxpoint/$divide" >> $tmpf2 echo "set label $k sprintf('%d',y) at 0,y offset .5,0" >> $tmpf2 @ j ++ end run3: ### gnuplot の描画 gnuplot -persist <<EOF if ( ! $gif ) set term x11 if ( $gif ) set term gif size 480,480 font 'ipag.ttf,10' if ( $gif ) set out "$image" set polar set size square unset tics set angle degree set xrange [-$maxpoint-${margin}:$maxpoint+$margin] set yrange [-$maxpoint-${margin}:$maxpoint+$margin] if ( $gif ) set title 'レーダーチャート' font 'ipam.ttf,14' if ( ! $gif ) set title 'レーダーチャート' N = $N M = $M pos(j,N) = 90 + j*360/N # j 番目の項目の偏角 # サブスクリプトのロード load "$tmpf2" # 描画 plot for [i=2:M+1] "$tmpf1" using (pos(column(0),N)):i \ title column(i) w lp pt 2+i, \ '' using (pos(column(0),N)):(column(M+2)) \ title column(M+2) w lp pt 0 lt -1,\ for [i=1:$divide] '' using (pos(column(0),N)):(i*$maxpoint/$divide) \ w lp notitle ps 1 pt 0 lt 0,\ '' using (pos(column(0),N)):($maxpoint+10):1 every ::1::N \ with labels notitle if ( $gif ) set out EOF run4: ### gif の場合は xli で画面出力 if ( $gif ) then xli $image endif
GIF 出力と x11 出力の切り替え用にさらに少し手が入っていますが、 基本的に上に紹介したものを全部入れたものです。 このように、awk スクリプト、gnuplot スクリプト、csh スクリプトを 一つにまとめて変数も共有すると、保守性はだいぶいいだろうと思います。
これを応用すれば、各人のデータと平均点のグラフのみ (2 本のグラフ) を、 グリッドやラベルつきで次々と出力するようにすることも可能で、 データから各人のグラフを自動的に生成することができます。
(cf. 「情報やメモ (03/28 2012)」, 「情報やメモ (01/29 2015)」, 「情報やメモ (03/29 2017; no.2)」, 「情報やメモ (04/06 2021)」)
先日、うちの大学の講義に関連して「バブルチャート」 なるグラフ形式を見たのですが、 はて、これは gnuplot で書けるんかいなと思ってやってみましたので、 ここにまとめておきます。
バブルチャートとは、3 次元的な散布データを、 2 次元平面上で表現する仕組みで、 各データ (xi,yi,zi) (zi>0) を 「中心 (xi,yi) で、半径 zi の円」の形で描画します。 ただ、単純にそのような円を各点毎に描くと、 小さい円と大きい円が重なった場合に小さい円があることがわからなくなるので、 通常は以下のように描かれているようです (これが正確なのかどうかは知りません)。
とりあえずこのようなものを描画してみることにします。 単に塗りつぶされた円盤を書いていくだけならば、 gnuplot-4.2 以降ならばそれほど難しくはなく、 "with points pointtype 7 pointsize variable" で描画すれば可能です:
sl=10.0pointtype 7 は中塗りの円 (円盤) の記号での点描画で、 pointsize variable は、3 列目のデータ ($3*sl) の値を点のサイズとします。 これで、各点の z の値に比例したサイズの円が描かれます。 sl は適当に大きくしないと小さい円のままです。 ただし、これは上のルール 1 しか満たしていません。
plot 'data' using 1:2:($3*sl) with points pt 7 lt 1 ps variable
ルール 2 を満たすようにするには、 データを z 値が大きいものから順に描画する必要があります。 これは、data を sort してから描画させればいいでしょう:
sl=10.0sort はデータをソーティングするツールで、 "+2 -3 -n -r" というオプションで、 3 列目のデータを (+2 -3)、数字として (-n)、 降順 (-r) でソーティングします。
plot '< sort +2 -3 -n -r data' using 1:2:($3*sl) \
with points pt 7 lt 1 ps variable
ルール 3 は、中塗りの円 (円盤) だけでなく、 円周を重ねて描けばいいのですが、それは pointtype 6 を使えばいいでしょう:
sl=10.0ところがこの書き方は、
plot '< sort +2 -3 -n -r data' \
using 1:2:($3*sl) with points pt 7 lt 1 ps variable, \
'' using 1:2:($3*sl) with points pt 6 lt 0 ps variable
1 行目のデータの円盤を書いて、のように描くので、これはルール 4 を満たさず、 すべての円の円周が潰されずに上 (最全面) に描かれてしまいます:
2 行目のデータの円盤を書いて、
...
1 行目のデータの円周を書いて、
2 行目のデータの円周を書いて、
...
1 1 2.3
2 3 3.5
3 5 1.5
4 1 5.1
2 1 4.0
1 2 2.0
ルール 4 を満たすようにするには、各円を、
1 行目のデータの円盤を書いて、円周を書いて、のような形で描かなければいけません。 円を描くには今のところこの手 (with points pt 7) しかありませんので、 1 点毎に円盤を書いて円周を書いて、 ということをやらないといけないでしょう。
2 行目のデータの円盤を書いて、円周を書いて、
...
CVS 版 gnuplot (4.3) では iteration 機能がありますので、 これと every を利用すれば 1 点毎の円を描くことができます:
# N はデータの行数ところが、この for では同時に 2 つの描画 (円盤と円周) を指定できませんので、 このままではだめで、少し工夫をする必要があり、例えば、 "for [i=1:N]" を "for [i=1:2*N]" に変えて、 以下のようにすればいけます:
plot for [i=1:N] '< sort +2 -3 -n -r data' using 1:2:($3*sl) \
every ::(i-1)::(i-1) with points pt 7 lt 1 ps variable notitle
# N はデータの行数「(i-1)/2」は、i が偶数の場合は切り捨てになるので、i/2 と同じになります。 これでルール 4 も満たされることになります。
ptf(i) = (i%2)? 7 : 6 # pointtype を i 毎に切り替え
ltf(i) = (i%2)? 1 : 0 # linetype を i 毎に切り替え
plot for [i=1:2*N] '< sort +2 -3 -n -r data' using 1:2:($3*sl) \
every ::((i-1)/2)::((i-1)/2) with points \
pt ptf(i) lt ltf(i) ps variable notitle
ただ、これにはもう一つ問題があり、 どうもこの point を拡大したものは、 グラフ領域でのクリッピングが行われないようで、 グラフ領域をはみだして描画されてしまいます:
これは gnuplot の軽いバグではないかと思いますが、 クリッピングは自前でもやろうと思えばできます。 gnuplot-4.2 以降には "set object rectangle front" がありますので、それでグラフ領域の外を消していって、 後で x 軸 y 軸の見出しをあらためて書き直せばいいわけです。 あらためて書き直すには、multiplot を使って上書きすればいいでしょう:
set multiplot"plot 1/0 notitle" は、軸の見出しを打つための空打ちです。
set style rectangle fc rgb 'white' fs solid 1.0 noborder
set object 1 rectangle from screen 0, graph 0 to screen 1, screen 0 front
set object 2 rectangle from screen 0, screen 0 to graph 0, screen 1 front
set object 3 rectangle from graph 1, screen 0 to screen 1, screen 1 front
set object 4 rectangle from screen 0, graph 1 to screen 1, screen 1 front
plot for [i=1:2*N] '< sort +2 -3 -n -r data' using 1:2:($3*sl) \
every ::((i-1)/2)::((i-1)/2) with points \
pt ptf(i) lt ltf(i) ps variable notitle
unset object 1
unset object 2
unset object 3
unset object 4
plot 1/0 notitle
unset multiplot
また、上ではデータの行数 (N) を使っていますが、 これも例えば system() でデータの行数を取得すれば可能です:
N = system('cat data | wc -l')データにコメント行などがある場合は、awk などで行を数えればいいでしょう:
N = system("awk '(!/^#/ && NF>=3){i++}END{print i}' data")ということで、以上をまとめると以下のようになります:
sl=10.0 set xrange [xmin:xmax] set yrange [ymin:ymax] N = system("awk '(!/^#/ && NF>=3){++i}END{print i}' data") ptf(i) = (i%2)? 7 : 6 # pointtype を i 毎に切り替え ltf(i) = (i%2)? 1 : 0 # linetype を i 毎に切り替え set title "Bubble chart" set multiplot set style rectangle fc rgb 'white' fs solid 1.0 noborder set object 1 rectangle from screen 0, graph 0 to screen 1, screen 0 front set object 2 rectangle from screen 0, screen 0 to graph 0, screen 1 front set object 3 rectangle from graph 1, screen 0 to screen 1, screen 1 front set object 4 rectangle from screen 0, graph 1 to screen 1, screen 1 front plot for [i=1:2*N] '< sort +2 -3 -n -r data' using 1:2:($3*sl) \ every ::((i-1)/2)::((i-1)/2) with points \ pt ptf(i) lt ltf(i) ps variable notitle unset object 1 unset object 2 unset object 3 unset object 4 plot 1/0 notitle unset multiplot
なお、上の 2 つのグラフを比較すればわかりますが、 指定した pointsize に対する実際の point のサイズは terminal 依存です。 よって最終的に出力する terminal に合わせて、 適宜 sl の値を調節する必要があります。
(cf. 「情報やメモ (03/13 2008)」, 「情報やメモ (03/15 2008)」, 「情報やメモ (04/03 2008)」, 「情報やメモ (05/07 2010)」)
gnuplot Q&A 掲示板 での見聞き等で得た情報を備忘録として書いておきます。
gnuplot で重回帰分析をしたい、という質問がありました。 私はその「重回帰分析」自体をよく知りませんが、 独立変数が複数の場合の回帰なのでしょうか、 そういう fitting も可能である、という回答がありました。
(1662 の記事から始まるスレッド 「重回帰分析について」)
松岡@名古屋大 さんから、Octave 用の wgnuplot/pgnuplot (Octave 用の特別な改造が含まれる)、 DJGPP 版の gnuplot に関する報告がありました。
DJGPP 版の gnuplot はなかなか使えるそうです。 これは日本語マニュアルも、 Shift_JIS (で CR+LF の改行コード) の gnuplot.gih が使えるようなので、 日本語マニュアルのその形式の公開も行うことにしました。
(1700 の記事から始まるスレッド 「Windows 上の gnuplot について」)
なお、DJGPP 版 gnuplot については、 1746 の記事 ( 「gp422dj2 の起動画面」) でも 引き続き松岡さんの紹介がありました。
gnuplot の fitting で得た回帰係数をファイルに記録したいのですが、 という質問がありました。 回数が多いので、手動でなく自動的に出力させたい、ということでした。
print コマンドで出力したり、update コマンドを使用する、 という回答が与えられましたが、 print コマンドのマニュアルを見てもよくわからない、 という話になって、調べてみるとマニュアルの日本語訳が 長いこと間違っていることに気がつきました。 失礼しました。
ついでに、マニュアルのその箇所は もう少し初心者にわかりやすい記述の方がいいのでは、 という意見もありました。 オンラインマニュアルは、徐々にわかりやすい形に改善されてきていますが、 それでも最小限の記述に留めるような形式を取っているようなので、 「初心者にわかりやすい」という形にするのは難しいかもしれません。
(1716 の記事から始まるスレッド 「値をファイルに出力」)
hidden3d を使うと滑らかな曲線が直線に置き換わってしまう、 という質問がありました。
上げられていた例は、筒とその上面を parametric mode で描画するようなものなのですが、 そこで "isosamples 9,9" のように荒いものが使われているため、 確かに hidden3d を使うと滑らかな円で書かれていたものが 折れ線に代わってしまいます。 これは、hidden3d の仕組み上しかたがないので、 isosamples の数字を上げるしかない、という回答がありました。 そしてそのサンプルの座標系の書き方に関する注意等がその後続きました。
(1736 の記事から始まるスレッド 「hidden コマンドについて」)
with boxes fs solid 1 とすると xtics や mxtics が棒グラフでつぶされてしまう、 という質問がありました (gnuplot-4.2.2)。
これに対して、
(1747 の記事から始まるスレッド 「棒グラフと x 軸目盛」)
前回の報告 (11/09 2007)以後、 現在の CVS 版に入れられた主な機能について紹介します (ChangeLog, manual の更新部分等より)。
utf8 encoding については、term/PostScript/unicode_maps.README に TrueType フォントから unicode encoding の pfa フォント (Type 1) を作る方法の説明などあります。
(cf. 「情報やメモ (04/04 2008)」)
2 ちゃんねるの掲示板「gnuplot を使おう。その 2」(アドレスは リンクリスト 参照) に書かれた情報について、多少気になるものがありましたので、 少し書いておきます。
凡例の文字列のフォントを変えたい、という質問がありました (296)。
key のフォントを変更するには、例えば以下の 2 通りの解があります (他にもなくはない)。
plot sin(x) title "{/font ...}"のように title 文字列を font を指定して記述する
CVS 版 gnuplot では set key でフォント指定ができるようになりました (gnuplot-4.2.X では不可) が、 最初の方なら CVS 版 gnuplot でなくても可能です。
gp422dj2.zip を本家のサイトからダウンロードしたんだけど、 使い方がわからない、という質問がありました (298)。
この "gp422dj2.zip" というのは、 Unix 版でも MS-Windows 版でもなく、「DJGPP 版」の gnuplot です。
元記事の方は、MS-Windows 版を望まれたのではないかと思いますが、 それなら gp422win32.zip をダウンロードするといいでしょう。 なお、DJGPP 版 gnuplot も、環境が整っていれば、 MS-Windows のコマンドプロンプト上で動かすことは可能だろうとは思います。
png terminal で日本語フォントを指定しているのだけど、 xtics と y2label を 90 度回転させようとしてもうまく回転しない、 という質問がありました (304)。
元記事の人は、以下のようにしているようです (詳しくは 304 の記事を参照):
最初の日本語フォントを使わないとうまくいくのだけど、 という話のようですが、 むしろ最初の set terminal の font 指定では 日本語フォントは指定しない方がいいだろうと思います。
set terminal のフォント指定で日本語フォントを指定してしまうと、 xtics の数字も含めすべての文字がそのフォントで書かれることになります。 それよりも、日本語が必要な場面で日本語フォントを指定する方が、 英数字は綺麗になるでしょう。 この記事の例では、set title だけが日本語なので、 set title で日本語フォントを指定すればいいわけです。
なお、日本語フォントがうまく回転しない場合がある件については、 「情報やメモ (03/08 2005)」 に情報があげてあります。
グラフの値の大きいものと小さいものを共存させて、 途中を波線で省略したグラフを書きたい、という話がありました (307)。
確かにそのようなグラフをたまに目にすることがあります。 これは、現在の CVS 版の gnuplot (4.3) を使えばできないことはありませんが、 少し面倒です。
途中の省略部分は、sin カーブを少し隙間を空けて描いて、 その間を with filledcurve で塗り潰すとかすればいいのですが、 問題は ytics です。 xtics や ytics の目盛りのつけ方は、 CVS 版でもプログラマブルにはなってはおらず、 手動、あるいは半自動的な方法によらざるを得ません。 よって、2 種類の異なる目盛りを同じ軸に重ねて書くには、 どうしても multiplot を使う必要があります。
また、with filledcurve で塗り潰す場合、 filledcurve は関数描画には使えず、データにしか対応していないので、 gnuplot-4.2.X でやろうとすると、 あらかじめ sin のグラフデータを作成しておかないといけません (または、set object rectangle の長方形の塗り潰しで我慢するか)。 CVS 版 gnuplot なら、疑似ファイル '+' を利用すれば sin カーブの with filledcurve がデータなしに行えます。 CVS 版 gnuplot 用のサンプルスクリプトを以下にあげます。
##### サンプルスクリプト for CVS 版 gnuplot-4.3 ##### ##### 初期設定 ##### ym1=0 yM1=10 ym2=50 yM2=60 ## 小さい値は [ym1:yM1] の間、大きい値は [ym2:yM2] の間とする。 yticsspace=5 ycutlen = 2 ## yticsspace: y 軸の刻み間隔、ycutlen: 波線の間隔 p=2.0 wave(x)=(ycutlen/2.0)*sin(p*x) ## 波線関数 f1(y) = (y>=ym1 && y<=yM1)? y:1/0 f2(y) = (y>=ym2 && y<=yM2)? y:1/0 ## f1(),f2(): それぞれ [ym1:yM1], [ym2:yM2] 内のデータのみ残す関数 set boxwidth 0.8 ## 描く棒グラフの幅 ##### 描画開始 ##### set multiplot ## まずは y2tics を y 軸に書くだけ set yrange [ym2-ycutlen-(yM1-ym1):yM2] set ytics ym2,yticsspace,yM2 ## 本来の y2range, y2tics を yrange, ytics とする unset y2tics unset border unset xtics unset key plot 'testbox1.dat' using 1:2 w boxes lt -2 ## lt -2: 空描画 ## 実際のグラフの描画 set yrange [ym1:yM1+yM2-ym2+ycutlen] set y2range [ym2-ycutlen-(yM1-ym1):yM2] ## 正しい yrange, y2range はこちら。 set ytics ym1,5,yM1 unset y2tics xmin=GPVAL_X_MIN xmax=GPVAL_X_MAX ## xmin, xmax: このデータに対する xrange set xrange [xmin:xmax] ## xrange の設定は波線用に必要。 set border set key set xtics plot 'testbox1.dat' using 1:(f1($2)) with boxes fs solid 1.0 lt 1 \ title 'small data',\ '' using 1:(f2($2)) axes x1y2 with boxes fs solid 1.0 lt 3 \ title 'large data',\ '+' using 1:(yM1+wave($1)):(yM1+ycutlen/2.0+wave($1)) \ with filledcurves notitle lt 5 ## plot の 1 つ目が小さいグラフ、2 つ目が大きいグラフ、 ## 3 つ目が波線部分 unset multiplot
1 1
2 2
3 3
4 54
5 55
6 56
けど、どうみても面倒ですね (^^;
(cf. 「情報やメモ (02/16 2010)」)