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


当前回答

我对Born2Smile的解决方案做了一些修改。

我知道这不太合理,但以防万一,你可能需要它。如果您的数据是整数,并且您需要一个浮动容器大小(可能是为了与另一组数据进行比较,或在更细的网格中绘制密度),您将需要在floor内添加一个0到1之间的随机数。否则,由于四舍五入误差会出现尖峰。地板(x/width+0.5)是不行的,因为它会创建与原始数据不相符的模式。

binwidth=0.3
bin(x,width)=width*floor(x/width+rand(0))

其他回答

我对Born2Smile的解决方案做了一些修改。

我知道这不太合理,但以防万一,你可能需要它。如果您的数据是整数,并且您需要一个浮动容器大小(可能是为了与另一组数据进行比较,或在更细的网格中绘制密度),您将需要在floor内添加一个0到1之间的随机数。否则,由于四舍五入误差会出现尖峰。地板(x/width+0.5)是不行的,因为它会创建与原始数据不相符的模式。

binwidth=0.3
bin(x,width)=width*floor(x/width+rand(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 

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

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

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

我们不需要使用递归方法,它可能会很慢。我的解决方案是使用用户定义的函数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函数和填充零