web-dev-qa-db-ja.com

gnuplotを使用したヒストグラム?

私の.datファイルに既に適切にビニングされたデータがある場合、gnuplotでヒストグラムを作成する方法(「with box」を使用)を知っています。数字のリストを取得し、gnuplotがユーザーが提供する範囲とビンサイズに基づいてヒストグラムを提供する方法はありますか?

197
mary

はい、非常に隠されていますが、すばやく簡単です:

binwidth=5
bin(x,width)=width*floor(x/width)

plot 'datafile' using (bin($1,binwidth)):(1.0) smooth freq with boxes

help smooth freqをチェックして、上記がヒストグラムを作成する理由を確認してください

範囲を扱うには、xrange変数を設定するだけです。

223
Born2Smile

Born2Smileの非常に便利な答えにいくつか修正/追加があります。

  1. 空のビンにより、隣接するビンのボックスが誤ってそのスペースに拡張されました。 set boxwidth binwidthを使用してこれを回避してください
  2. Born2Smileのバージョンでは、ビンは下限を中心としてレンダリングされます。厳密には、下限から上限まで拡張する必要があります。これは、bin関数を変更することで修正できます:bin(x,width)=width*floor(x/width) + width/2.0
86
mas90

非常に注意してください:このページのすべての回答は、ビニングの開始場所(必要に応じて左端のビンの左端)をユーザーの手から暗黙的に決定しています。ユーザーがデータをビニングするためのこれらの機能のいずれかを、ビニングの開始場所に関する独自の決定と組み合わせている場合(上記にリンクされているブログで行われているように)、上記の機能はすべて正しくありません。 「Min」をビニングするための任意の開始点では、正しい関数は次のとおりです。

bin(x) = width*(floor((x-Min)/width)+0.5) + Min

これが順番に正しい理由を確認できます(いくつかのビンとその中のどこかにポイントを描画すると役立ちます)。データポイントからMinを減算して、ビニング範囲内の距離を確認します。次に、「ビン」の単位で効果的に作業できるように、ビン幅で分割します。次に、結果を「フロア化」してそのビンの左端に移​​動し、0.5を追加してビンの中央に移動し、幅を乗算して、ビン単位ではなく絶対スケールで作業するようにします繰り返しますが、最後に開始時に減算した最小オフセットを追加し直します。

動作中のこの機能を検討してください。

Min = 0.25 # where binning starts
Max = 2.25 # where binning ends
n = 2 # the number of bins
width = (Max-Min)/n # binwidth; evaluates to 1.0
bin(x) = width*(floor((x-Min)/width)+0.5) + Min

例えば値1.1は、実際に左のビンに該当します。

  • この関数は、左ビンの中心(0.75)に正しくマップします。
  • Born2Smileの答え、bin(x)= width * floor(x/width)は、誤って1にマップします。
  • mas90の答え、bin(x)= width * floor(x/width)+ binwidth/2.0は、誤って1.5にマッピングします。

Born2Smileの答えは、ビンの境界が(n + 0.5)* binwidth(nは整数を超える)で発生する場合にのみ正しいです。 mas90の答えは、ビンの境界がn * binwidthで発生する場合にのみ正しいです。

76
ChrisW

このようなグラフをプロットしますか? enter image description here はい?次に、私のブログ記事をご覧ください: http://gnuplot-surprising.blogspot.com/2011/09/statistic-analysis-and-histogram.html

コードの重要な行:

n=100 #number of intervals
max=3. #max value
min=-3. #min value
width=(max-min)/n #interval width
#function used to map a value to the intervals
hist(x,width)=width*floor(x/width)+width/2.0
set boxwidth width*0.9
set style fill solid 0.5 # fill style

#count and plot
plot "data.dat" u (hist($1,width)):(1.0) smooth freq w boxes lc rgb"green" notitle
45
hsxz

いつものように、Gnuplotは見栄えの良いグラフをプロットするための素晴らしいツールであり、あらゆる種類の計算を実行するように作成できます。 ただし、計算機として機能するのではなくデータをプロットすることを目的としています。多くの場合、外部プログラム(たとえば、Octave)を使用してより複雑な計算を行い、このデータをファイル、Gnuplotを使用してグラフを作成します。上記の問題については、[freq,bins]=hist(data)を使用して「hist」関数がOctaveであることを確認してから、これをGnuplotでプロットします。

set style histogram rowstacked gap 0
set style fill solid 0.5 border lt -1
plot "./data.dat" smooth freq with boxes
9
Dai

この議論は非常に有用であることがわかりましたが、いくつかの「四捨五入」問題が発生しました。

より正確には、0.05のビン幅を使用して、上記の手法では、0.1と0.15を読み取るデータポイントが同じビンに入ることに気付きました。これ(明らかに望ましくない動作)は、おそらく「フロア」機能によるものです。

以下は、これを回避しようとする私の小さな貢献です。

bin(x,width,n)=x<=n*width? width*(n-1) + 0.5*binwidth:bin(x,width,n+1)
binwidth = 0.05
set boxwidth binwidth
plot "data.dat" u (bin($1,binwidth,1)):(1.0) smooth freq with boxes

この再帰的メソッドはx> = 0向けです。より一般的な何かを得るために、これをより条件付きのステートメントで一般化できます。

7
Alex

再帰的な方法を使用する必要はありません。遅いかもしれません。私の解決策は、組み込み関数intまたはfloorのユーザー定義関数rint instesdを使用しています。

rint(x)=(x-int(x)>0.9999)?int(x)+1:int(x)

この関数はrint(0.0003/0.0001)=3を、int(0.0003/0.0001)=floor(0.0003/0.0001)=2を返します。

どうして? Perl int関数とパディングゼロ をご覧ください

6
JOE

Born2Smileのソリューションに少し変更を加えました。

私はそれがあまり意味をなさないことを知っています、しかしあなたは念のためにそれを望むかもしれません。データが整数で、フロートビンサイズが必要な場合(別のデータセットとの比較、またはより細かいグリッドでのプロット密度のため)、フロア内に0から1の間の乱数を追加する必要があります。そうしないと、切り上げエラーによるスパイクが発生します。 floor(x/width+0.5)は、元のデータに当てはまらないパターンを作成するため、実行しません。

binwidth=0.3
bin(x,width)=width*floor(x/width+Rand(0))
4
path4

関数のビニングに関しては、これまでに提供された関数の結果を期待していませんでした。つまり、ビン幅が0.001の場合、これらの関数はビンを0.0005ポイントにセンタリングしていましたが、ビンを0.001境界にセンタリングする方が直感的だと感じています。

言い換えれば、私はしたい

Bin 0.001 contain data from 0.0005 to 0.0014
Bin 0.002 contain data from 0.0015 to 0.0024
...

私が思いついたビニング機能は

my_bin(x,width)     = width*(floor(x/width+0.5))

提供されているビン関数のいくつかをこれと比較するスクリプトを次に示します。

rint(x) = (x-int(x)>0.9999)?int(x)+1:int(x)
bin(x,width)        = width*rint(x/width) + width/2.0
binc(x,width)       = width*(int(x/width)+0.5)
mitar_bin(x,width)  = width*floor(x/width) + width/2.0
my_bin(x,width)     = width*(floor(x/width+0.5))

binwidth = 0.001

data_list = "-0.1386 -0.1383 -0.1375 -0.0015 -0.0005 0.0005 0.0015 0.1375 0.1383 0.1386"

my_line = sprintf("%7s  %7s  %7s  %7s  %7s","data","bin()","binc()","mitar()","my_bin()")
print my_line
do for [i in data_list] {
    iN = i + 0
    my_line = sprintf("%+.4f  %+.4f  %+.4f  %+.4f  %+.4f",iN,bin(iN,binwidth),binc(iN,binwidth),mitar_bin(iN,binwidth),my_bin(iN,binwidth))
    print my_line
}

そして、これが出力です

   data    bin()   binc()  mitar()  my_bin()
-0.1386  -0.1375  -0.1375  -0.1385  -0.1390
-0.1383  -0.1375  -0.1375  -0.1385  -0.1380
-0.1375  -0.1365  -0.1365  -0.1375  -0.1380
-0.0015  -0.0005  -0.0005  -0.0015  -0.0010
-0.0005  +0.0005  +0.0005  -0.0005  +0.0000
+0.0005  +0.0005  +0.0005  +0.0005  +0.0010
+0.0015  +0.0015  +0.0015  +0.0015  +0.0020
+0.1375  +0.1375  +0.1375  +0.1375  +0.1380
+0.1383  +0.1385  +0.1385  +0.1385  +0.1380
+0.1386  +0.1385  +0.1385  +0.1385  +0.1390
3
Winston Smith