gnuplot の初歩（ワンライナーを中心に）#1


[#1](https://qiita.com/bunzaemon/items/1266c012c09e22e5690c)/[#2](https://qiita.com/bunzaemon/items/24d5b36879758c38ff71)/[#3](https://qiita.com/bunzaemon/items/d7bd76c1cdad196e566b)

## 前提

- 5.2系での確認(-cとか使用)
- –persist(-p) オプションを使用。

-p は OS X だとそれなり設定しないと使えません。

-pが設定されてない環境では、~/.gnuplotファイルを設定して、置き換えてから読むと良いかも(一番最後に触れてます)。


# 初歩

## print できますよ。
```
$ gnuplot -e 'print "foo"'
foo
```

標準エラー出力に出力されます。

## 四則演算ができますよ。

```
$ gnuplot -e 'print 0.1 + 2'
2.1
```
## 関数がプロットできますよ。

y=x

```
$ gnuplot -p -e 'plot x'
```

## 単純なグラフなら、即表示できますよ。

```
# データ作成
$ perl -le 'print rand (10) for 0 .. 99' > rand.txt
$ gnuplot -p -e 'f="rand.txt";' -e 'plot f w l'
```
![rand.png](https://qiita-image-store.s3.amazonaws.com/0/64084/e9bd7c7b-ae64-feb3-7170-b604503896f2.png "rand.png")


## コマンドライン引数も使えますよ

>-c scriptname ARG1 ARG2 ..., load script using gnuplot's "call"  mechanism
       and pass it the remainder of the command line as arguments

これをワンライナーで使わない手はない。って事で。

```
$ gnuplot -p -c <( echo 'plot ARG1 w l' ) rand.txt
```

この、「なんちゃってワンライナー」は、bash のプロセス置換と -c で実現。
他のシェルを使ってる人は、それぞれ、該当機能を利用。

**以降、なんちゃってワンライナーで説明します。**

# 変数とか

## 定義されてる変数

をみることができますよ。

```
$ gnuplot -c <( echo 'show variables all' ) rand.txt
        All available variables:
        pi = 3.14159265358979
        GNUTERM = "qt"
        NaN = NaN
        GPVAL_TERM = "qt"
(後略)
```


### 描画範囲


例えば、オートスケールでのグラフの上と下の値が知りたければ、

```
$ gnuplot -p -c <( echo 'plot ARG1; print GPVAL_Y_MIN, GPVAL_Y_MAX ;' ) rand.txt 
0.0 10.0
```

一回プロットしなければ、オートスケールの幅の値はわからないから、

```
$  gnuplot -p -c <( echo 'plot ARG1; print GPVAL_Y_MIN, GPVAL_Y_MAX ;set yrange [GPVAL_Y_MIN + 1:GPVAL_Y_MAX + 2] ; replot' ) rand.txt
```

などとして利用する事も出来る。

オートスケールの図自体は変更せずに、もう一つ線を描かざるを得なくなった時とかに使う[^1]。

[^1]: オートスケールで提出したグラフに追加が来て、「アレ？グラフ幅変わったよね？元に戻してよ。」なんて不毛なことにならない様に！！

### 引数
さらっと、上で使ってるけど、-c 指定時、引数全ては、ARGV に配列として入ってて、ARGCで数が分る。

```
# 2つめのデータ作成
$ perl -le 'print rand (10) for 0 .. 99' > rand2.txt
$ gnuplot -c <( echo 'print ARGV' ) rand.txt rand2.txt
["rand.txt","rand2.txt"]
$ gnuplot -c <( echo 'print ARGC' ) rand.txt rand2.txt
2
```

配列だから、ARGV[1], ARGV[2] でアクセス出来るけど、ARG1, ARG2 でアクセスする事も出来る。多分、後者を使う方が安全。



## 統計変数

統計もとれますよ。

統計といっても、最大値、最小値、平均値あたりだけでも利用する価値があるので、数学苦手でも、スルーしない。

```
$ gnuplot -p -c <( echo 'stats ARG1' ) rand.txt  |& less

* FILE:
  Records:           100
  Out of range:        0
  Invalid:             0
(中略)

  Minimum:            0.2004 [ 89]
  Maximum:            9.9960 [ 50]
  Quartile:           2.4146
  Median:             5.6570
  Quartile:           8.0762
```

統計結果は変数になっている(STATS_*)。

ex) STATS_mean, STATS_max, STATS_min

その変数がどうなってるかを見たければ、 show variable

nooutput を指定すると統計結果を出力しない。

```
$ gnuplot -p -c <( echo 'stats ARG1 nooutput; show variable' ) rand.txt
(前略)
	STATS_mean = 5.243808700483
(中略)	
	STATS_min = 0.200399722348834
	STATS_max = 9.99601809448972
	STATS_median = 5.65700853835128
	STATS_lo_quartile = 2.41458258388167
	STATS_up_quartile = 8.07619942631923
	STATS_index_min = 89
	STATS_index_max = 50
```

カラム数が加わるごとに、統計の変数名は変化するので注意。

```
# X,Yのデータにしてみる
$ perl -le 'print join " ", $_, rand (10) for 0 .. 99' > randwx.txt
$ gnuplot -p -c <( echo 'stats ARG1 nooutput; show variable' ) rand.txt
# 抜粋
	STATS_min_x = 0.0
	STATS_max_x = 99.0
	STATS_index_min_x = 0
	STATS_index_max_x = 99
	STATS_min_y = 0.0154784892457727
	STATS_max_y = 9.99397791792269
	STATS_index_min_y = 44
	STATS_index_max_y = 83
```

### 範囲指定

X をまともに宣言していれば、XY の範囲を [*:*] [*:*] で宣言する事も出来る。

```
# Xが、1から10の範囲
# Yが、1から7の範囲
$ gnuplot -p -c <( echo 'stats [1:10] [1:7] ARG1' ) randwx.txt
* FILE:
  Records:           9
  Out of range:      91
  Invalid:           0
  Column headers:    0
  Blank:             0
  Data Blocks:       1

* COLUMNS:
  Mean:               5.4444            4.9992
(中略)
  Minimum:            1.0000 [0]        3.2951 [2]
  Maximum:           10.0000 [8]        6.3608 [0]
  Quartile:           3.0000            4.0221
  Median:             5.0000            5.0543
  Quartile:           8.0000            5.9663

  Linear Model:       y = -0.1782 x + 5.97
  Slope:              -0.1782 +- 0.1202
  Intercept:          5.97 +- 0.7485
  Correlation:        r = -0.4889
  Sum xy:             230.3
```

レコードの数が、9になっていて、X(第2カラム)、Y(第3カラム)のそれぞれの数値が変化しているのが分る。


ただし、別の方法もあって、

```
$ gnuplot -p -c <( echo 'stats ARG1 every ::0::9' ) rand.txt 
# 行の位置が0ポイントから9ポイントまでの間
```

みたいに every を使う方法もある。
こっちは、データ行が一列の場合でも使える。
最初の何サンプルかの平均値を中心にもってきて描画したい場合などに便利。

```
$ gnuplot -p -c <( echo 'stats ARG1 every ::0::9 nooutput ; plot [*:*] [STATS_mean-5:STATS_mean+5] ARG1 w l' ) rand.txt
```
![rand_cut.png](https://qiita-image-store.s3.amazonaws.com/0/64084/97229e05-f7ea-2eba-70b9-931ca9cbca60.png "rand_cut.png")

### 応用

複数ファイルの中での最大最小を出すとかもできる。

```shell-session:A
$ perl -le 'print rand (10) for 0 .. 99' > rand3.txt
$ gnuplot -p -c <( echo 'stats "< cat " . ARG1 . " ". ARG2' ) rand.txt rand2.txt
(略)
```

最大最小の値のところに印をつけるとか、簡単にできる。

```
$ gnuplot -p  -c <(echo 'stats ARG1 nooutput ; plot ARG1 w l, "+" using (STATS_index_min):(STATS_min)  lw 3 w p ' ) rand.txt
```

'+' はスペシャルファイルネーム。

>
There are a few filenames that have a special meaning: ’ ’, ’-’, ’+’ and ’++’.

この疑似ファイル名が与えられると、using (X):(Y)で、直接値を指定できる。

![rand_min.png](https://qiita-image-store.s3.amazonaws.com/0/64084/07203dec-ee59-80ff-f34a-0bc8934e5b3f.png "rand_min.png")



**余談: perl での join 相当**

用意されてないっぽいなあ。

上の A とか引数の数が多いと、いちいち書くのめんどい。

仕方ないので、

```
$ gnuplot -p -c <( echo 's="" ; do for [i = 1:ARGC] { s = s. " " . ARGV[i] } ; stats "< cat" . s' ) rand.txt rand2.txt ...
```

で、お茶を濁す。

# ライブラリっぽく

~/.gnuplot を自動的に読み込むので、

```
$ cat ~/.gnuplot
set terminal png
set output "test.png"
```

などとすれば、毎回test.pngに描画される様になる。

## 個別に指定したい場合


load FILE を使う。

```
$ cat /PATH/TO/.gnuplot
set print '-' #  print コマンドの出力先を標準出力に変える。
$ alias gnuplot="gnuplot -e 'load \"/PATH/TO/.gnuplot\" ' 
$ gnuplot -c <( echo 'print "hoge"') 1> /dev/null
$ 
```

但し、~/.gnuplotを同時には読み込まない。


### GNUPLOT_LIB

パスを登録することで、 ライブラリファイルを指定しやすくする事が出来る。

```
$ cat /PATH/TO/.test
set print '-' 
$ export GNUPLOT_LIB=/PATH/TO
$ gnuplot -c <( echo 'load ".test" ; print "hoge"') 1> /dev/null
$
```