212

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

4

10 に答える 10

236

はい、そして非常に隠されていますが、その迅速でシンプルです:

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変数を設定するだけです。

于 2010-03-29T14:52:21.310 に答える
96

Born2Smileの非常に有用な答えにいくつかの修正/追加があります:

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

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

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

これが順番に正しい理由がわかります(いくつかのビンとそれらの1つのどこかにポイントを描画するのに役立ちます)。データポイントから最小値を引いて、ビニング範囲にどれだけ入っているかを確認します。次に、binwidthで除算して、「bins」の単位で効果的に作業できるようにします。次に、結果を「フロア」してそのビンの左端に移​​動し、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で発生する場合にのみ正しいです。

于 2013-10-25T17:37:05.303 に答える
52

このようなグラフをプロットしますか? ここに画像の説明を入力してください はい?次に、私のブログ記事を見ることができます: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
于 2011-09-17T11:00:53.517 に答える
10

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

set style histogram rowstacked gap 0
set style fill solid 0.5 border lt -1
plot "./data.dat" smooth freq with boxes
于 2014-06-25T13:03:36.380 に答える
7

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

より正確には、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の場合です。これをより条件付きのステートメントで一般化して、さらに一般的なものを取得することができます。

于 2012-03-27T15:10:58.487 に答える
6

再帰的な方法を使用する必要はありません。遅い場合があります。私の解決策は、本能関数intまたはfloorのユーザー定義関数rintinstesdを使用することです。

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関数とパディングゼロを見てください

于 2012-11-17T17:24:17.373 に答える
5

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

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

binwidth=0.3
bin(x,width)=width*floor(x/width+rand(0))
于 2013-12-02T14:58:17.017 に答える
3

ビニング関数に関しては、これまで提供されていた関数の結果を期待していませんでした。つまり、ビン幅が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))

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

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
于 2014-07-24T00:43:36.257 に答える
0

同じデータセットのビンの数が異なると、データの異なる特徴が明らかになる可能性があります。

残念ながら、ビンの数を決定できる普遍的な最良の方法はありません。

強力な方法の1つは、フリードマン・ダイアコニス規則です。これは、他の多くの選択肢の中でも、特定のデータセットの統計に基づいてビンの数を自動的に決定します。

gnuplotしたがって、以下を使用して、スクリプトでフリードマン・ダイアコニス規則を利用できます。

サンプルの単一の列を含むファイルがあるとしますsamplesFile

# samples
0.12345
1.23232
...

以下( ChrisWの回答に基づく)を既存のgnuplotスクリプトに埋め込むことができます。

...
## preceeding gnuplot commands
...

#
samples="$samplesFile"
stats samples nooutput
N = floor(STATS_records)
samplesMin = STATS_min
samplesMax = STATS_max
# Freedman–Diaconis formula for bin-width size estimation
    lowQuartile = STATS_lo_quartile
    upQuartile = STATS_up_quartile
    IQR = upQuartile - lowQuartile
    width = 2*IQR/(N**(1.0/3.0))
    bin(x) = width*(floor((x-samplesMin)/width)+0.5) + samplesMin

plot \
    samples u (bin(\$1)):(1.0/(N*width)) t "Output" w l lw 1 smooth freq 
于 2021-02-20T13:46:58.610 に答える