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の値が平均化したいデータの間でそろっていないので、単純に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
オプションが使えるようになります。(※↓でlc
やlt
を変更しているのは見やすくするためで、特に大きな意味は有りません))
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"