データを平均化する

gnuplotのsmooth uniqueオプションを使うと、データのうち同じxの値を持つものを平均化します。

単純な平均化

以下のようなデータdata.datをプロットすることを考えます。

0	1
0	3
0	6
1	2
1	-1
1	0
1	9
2	7
2	6
2	5
2	4
3	1
3	3

このファイルをプロットする際に、smooth uniqueというオプションを付け加えると、同じxの値を持つデータを平均化してくれます。例えば、下のようなスクリプトで上のデータファイルをプロットするします。

set xrange [-0.5:3.5]
plot "data.dat" u 1:2 title "raw data", \
     "" u 1:2 smooth unique title "averaged data"

すると、結果は以下のようになります。たしかに、smooth uniqueをつけた方は、1列目の値が同じものをそれぞれ平均化していることが分かります。

xの値がバラバラなデータの平均化

実際に実験等をしていると、上のようにxの値がきれいにそろっているデータ以外も平均化を行いたい場合がよくあります。例えば、下の図のようにノイズが大きいデータをあるxの範囲内で平均化することができればノイズをある程度低減することができるはずです。

しかし、この場合はxの値が平均化したいデータの間でそろっていないので、単純にsmooth uniqueオプションをつけただけでは、下図のように平均化はうまくされません。

そこで、下のような関数filter(x,y)を導入します。

nearint(x)=(x - floor(x) <= 0.5 ? floor(x) : floor(x)+1) # 一番近い整数に丸める関数
filter(x,y)=nearint(x/y)*y                                  # yの整数倍に丸める関数

この関数は、nを整数値として、(n-0.5)yと(n+0.5)yの間の数をすべてnyに丸めてしまう関数です。この関数をプロットしてみると、確かにそのようになっていることが分かります。

データのxの値にこの関数を噛ませることで、smooth uniqueオプションが使えるようになります。(※↓でlcltを変更しているのは見やすくするためで、特に大きな意味は有りません))

plot "noisy_data.dat" u 1:2 lc rgb "gray" title "raw data", \
     "" u (filter($1,0.05)):2 smooth unique lt 1 title "smoothed data"

上のスクリプトの実行結果は以下の通りです。確かに、意図したとおり平均化が行われノイズが低減されていることが分かります。

なお、下に示すように、filter()関数の第2引数を大きくすると、より多くのデータを平均化するためノイズ低減の効果は大きくなります。一方、平均化しすぎると重要な情報も失われてしまう可能性があるので注意が必要です。例えば以下の例では、x=2.4の付近のデータのシャープな変化が、平均化を強くするとなまってきてしまっていることが分かると思います。どの程度の範囲で平均化をするかは常に慎重な吟味が必要です。

plot "noisy_data.dat" u 1:2 lc rgb "gray" title "raw data", \
     "noisy_data.dat" u (filter($1,0.01)):2 smooth unique  lt 2 title "smoothed data y=0.01",\
     "" u (filter($1,0.05)):2 smooth unique lt 3 title "smoothed data y=0.05",\
     "" u (filter($1,0.2)):2 smooth unique lt 1 title "smoothed data y=0.2"