我知道如何在gnuplot中创建直方图(只是使用“带框”),如果我的.dat文件已经有正确的二进制数据。是否有一种方法可以获取数字列表,并让gnuplot根据用户提供的范围和bin大小提供一个直方图?


当前回答

你想画一个像这样的图吗? 是吗?然后你可以看看我的博客文章: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

其他回答

要非常小心:本页上的所有答案都隐含地决定了装箱从哪里开始——如果你喜欢的话,从最左边的箱子的左边边缘开始——而不是由用户决定。如果用户将这些函数中的任何一个与他/她自己决定的数据分箱开始位置相结合(就像在上面链接的博客上所做的那样),上述函数都是不正确的。对于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时才正确。

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

我们不需要使用递归方法,它可能会很慢。我的解决方案是使用用户定义的函数rint,而不是内部函数int或floor。

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函数和填充零

我对Born2Smile非常有用的答案有一些更正/补充:

空箱子导致相邻箱子的箱子不正确地延伸到它的空间;使用set boxwidth binwidth避免这种情况 在Born2Smile的版本中,箱子以下界为中心呈现。严格来说,它们应该从下界延伸到上界。这可以通过修改bin函数来纠正:bin(x,width)=width*floor(x/width) + width/2.0

我发现这个讨论非常有用,但我也遇到过一些“四舍五入”的问题。

更准确地说,使用0.05的binwidth,我注意到,使用上面介绍的技术,读取0.1和0.15的数据点落在同一个bin中。这(显然是不想要的行为)很可能是由于“地板”功能。

下面是我的小贡献,试图规避这一点。

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;我们可以用更多的条件语句来概括它,从而得到更一般的结果。