我知道如何在gnuplot中创建直方图(只是使用“带框”),如果我的.dat文件已经有正确的二进制数据。是否有一种方法可以获取数字列表,并让gnuplot根据用户提供的范围和bin大小提供一个直方图?
当前回答
我对Born2Smile非常有用的答案有一些更正/补充:
空箱子导致相邻箱子的箱子不正确地延伸到它的空间;使用set boxwidth binwidth避免这种情况 在Born2Smile的版本中,箱子以下界为中心呈现。严格来说,它们应该从下界延伸到上界。这可以通过修改bin函数来纠正:bin(x,width)=width*floor(x/width) + width/2.0
其他回答
同一数据集上不同数量的箱子可以揭示数据的不同特征。
不幸的是,没有通用的最佳方法可以确定箱子的数量。
其中一个强大的方法是Freedman-Diaconis规则,它根据给定数据集的统计数据自动确定箱子的数量,还有许多其他的替代方法。
因此,下面的代码可以在gnuplot脚本中使用Freedman-Diaconis规则:
假设你有一个文件,它只包含一列样本,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
是的,它快速而简单,但非常隐蔽:
binwidth=5
bin(x,width)=width*floor(x/width)
plot 'datafile' using (bin($1,binwidth)):(1.0) smooth freq with boxes
查看帮助平滑频率,看看为什么上面做了一个直方图
要处理范围,只需设置xrange变量。
As usual, Gnuplot is a fantastic tool for plotting sweet looking graphs and it can be made to perform all sorts of calculations. However, it is intended to plot data rather than to serve as a calculator and it is often easier to use an external programme (e.g. Octave) to do the more "complicated" calculations, save this data in a file, then use Gnuplot to produce the graph. For the above problem, check out the "hist" function is Octave using [freq,bins]=hist(data), then plot this in Gnuplot using
set style histogram rowstacked gap 0
set style fill solid 0.5 border lt -1
plot "./data.dat" smooth freq with boxes
要非常小心:本页上的所有答案都隐含地决定了装箱从哪里开始——如果你喜欢的话,从最左边的箱子的左边边缘开始——而不是由用户决定。如果用户将这些函数中的任何一个与他/她自己决定的数据分箱开始位置相结合(就像在上面链接的博客上所做的那样),上述函数都是不正确的。对于bin 'Min'的任意起始点,正确的函数是:
bin(x) = width*(floor((x-Min)/width)+0.5) + Min
You can see why this is correct sequentially (it helps to draw a few bins and a point somewhere in one of them). Subtract Min from your data point to see how far into the binning range it is. Then divide by binwidth so that you're effectively working in units of 'bins'. Then 'floor' the result to go to the left-hand edge of that bin, add 0.5 to go to the middle of the bin, multiply by the width so that you're no longer working in units of bins but in an absolute scale again, then finally add back on the Min offset you subtracted at the start.
考虑这个函数:
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确实落在左bin中:
这个函数正确地将它映射到左bin的中心(0.75); Born2Smile的答案,bin(x)=width*floor(x/width),错误地将其映射为1; Mas90的答案,bin(x)=width*floor(x/width) + binwidth/2.0,错误地将其映射为1.5。
Born2Smile的答案只有在bin边界出现在(n+0.5)*binwidth (n经过整数)时才正确。Mas90的答案只有在bin边界出现在n*binwidth时才正确。
我对Born2Smile非常有用的答案有一些更正/补充:
空箱子导致相邻箱子的箱子不正确地延伸到它的空间;使用set boxwidth binwidth避免这种情况 在Born2Smile的版本中,箱子以下界为中心呈现。严格来说,它们应该从下界延伸到上界。这可以通过修改bin函数来纠正:bin(x,width)=width*floor(x/width) + width/2.0