使用gnuplot的直方图?

使用gnuplot的直方图?,gnuplot,histogram,binning,Gnuplot,Histogram,Binning,如果我的.dat文件已经有了正确的装箱数据,我知道如何在gnuplot中创建直方图(只需使用“with box”)。有没有一种方法可以获取数字列表,并让gnuplot根据用户提供的范围和箱子大小提供直方图?是的,它快速简单,但非常隐蔽: binwidth=5 bin(x,width)=width*floor(x/width) plot 'datafile' using (bin($1,binwidth)):(1.0) smooth freq with boxes 查看help smooth f

如果我的.dat文件已经有了正确的装箱数据,我知道如何在gnuplot中创建直方图(只需使用“with box”)。有没有一种方法可以获取数字列表,并让gnuplot根据用户提供的范围和箱子大小提供直方图?

是的,它快速简单,但非常隐蔽:

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变量。

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

  • 空箱子导致相邻箱子的箱子错误地伸入其空间;使用
    set-boxwidth-binwidth
  • 在Born2Smile的版本中,垃圾桶被渲染为以其下限为中心。严格来说,它们应该从下限延伸到上限。这可以通过修改
    bin
    功能来纠正:
    bin(x,宽度)=宽度*地板(x/宽度)+宽度/2.0

  • 你想画一个像这样的图吗? 对然后你可以看看我的博客文章:

    代码中的关键行:

    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
    

    我发现这个讨论非常有用,但我遇到了一些“圆满”的问题

    更准确地说,使用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
    

    bin(x,宽度,n)=x=0;我们可以用更多的条件语句来概括这一点,以获得更一般的结果。

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


    为什么??请仔细阅读

    请注意:本页上的所有答案都隐含着从用户手中决定装箱的开始位置-最左侧箱子的左侧边缘,如果您愿意的话。如果用户将这些用于装箱数据的功能与他/她自己关于装箱从何处开始的决定相结合(正如在上面链接的博客上所做的),则上述功能都是不正确的。对于装箱“Min”的任意起点,正确的函数是:

    bin(x) = width*(floor((x-Min)/width)+0.5) + Min
    
    你可以看到为什么这是正确的顺序(它有助于画几个箱子和一个点在其中的某个地方)。从数据点中减去Min,以查看它在装箱范围内有多远。然后除以binwidth,这样就可以有效地以“箱子”为单位工作。然后“地板”将结果移到该箱子的左边缘,再加上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
    
    e、 g.值1.1真正落在左侧箱子中:

    • 此功能可将其正确映射到左侧储物箱的中心(0.75)
    • Born2Smile的答案是bin(x)=width*floor(x/width),错误地将其映射为1
    • mas90的答案,bin(x)=宽度*地板(x/宽度)+bin宽度/2.0,错误地将其映射到1.5

    Born2Smile的答案只有在(n+0.5)*binwidth(其中n在整数上运行)出现bin边界时才是正确的。mas90的答案只有在料仓边界出现在n*binwidth时才是正确的。

    我对Born2Smile的解做了一些修改

    我知道这没有多大意义,但你可能想要以防万一。如果您的数据是整数,并且您需要浮点数大小(可能是为了与另一组数据进行比较,或者在更精细的网格中绘制密度),则需要在地板内部添加一个介于0和1之间的随机数。否则,由于舍入误差将出现峰值<代码>地板(x/width+0.5)
    将不起作用,因为它将创建与原始数据不符的图案

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

    和往常一样,Gnuplot是绘制漂亮图形的绝佳工具,可以让它执行各种计算然而,它用于绘制数据,而不是用作计算器,使用外部程序(如倍频程)进行更“复杂”的计算,将数据保存在文件中,然后使用Gnuplot生成图形通常更容易。对于上述问题,请使用
    [freq,bins]=hist(data)
    检查“hist”函数是否为倍频程,然后使用

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

    关于bining函数,我没有想到到目前为止提供的函数会有这样的结果。也就是说,如果我的binwidth是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
    ...
    
    我提出的binning函数是

    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
    

    同一数据集上不同数量的存储箱可以显示数据的不同特征

    不幸的是,没有通用的最佳方法可以确定垃圾箱的数量

    其中一个强大的方法是,它根据给定数据集的统计信息自动确定存储箱的数量

    因此,以下内容可用于在
    gnuplot
    脚本中使用Freedman–Diaconis规则:

    ...
    ## 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 
    
    假设您有一个包含单个样本列的文件,
    samplesFile

    # samples
    0.12345
    1.23232
    ...
    
    以下内容(基于)可以嵌入到现有的
    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 
    

    如果你没有得到答案,还有其他工具可以用来做这些事情。我使用Root()这里很多其他人使用R,至少还有一些其他选项