在 bash 中创建直方图

Che*_*n17 3 bash awk loops histogram

编辑

我读过这个问题,这应该是(this one)的副本。我不同意。在那个问题中,目的是获得列中各个数字的频率。但是,如果我将该解决方案应用于我的问题,我仍然会遇到将特定范围内数字的频率分组到最终直方图的初始问题。即,如果该解决方案告诉我0.45is20.44is的频率1(对于我的输入数据),我仍然面临将这两个频率分组3为范围的总和的问题0.4-0.5

结束编辑

题-

我有一长列数据,其值介于 0 和 1 之间。这将是以下类型 -

0.34
0.45
0.44
0.12
0.45
0.98
.
.
.
Run Code Online (Sandbox Code Playgroud)

允许重复的一长列十进制值。

我正在尝试将其更改为直方图类型的输出,例如(对于上面显示的输入)-

0.0-0.1  0
0.1-0.2  1
0.2-0.3  0
0.3-0.4  1 
0.4-0.5  3
0.5-0.6  0
0.6-0.7  0
0.7-0.8  0
0.8-0.9  0
0.9-1.0  1
Run Code Online (Sandbox Code Playgroud)

基本上,第一列具有每个范围的下限和上限,第二列具有该范围内的条目数。

我把它(糟糕地)写成——

for i in $(seq 0 0.1 0.9)
do 
    awk -v var=$i '{if ($1 > var && $1 < var+0.1 ) print $1}' input | wc -l; 
done
Run Code Online (Sandbox Code Playgroud)

它基本上做了wc -l它在每个范围内找到的条目。

输出格式不是问题的一部分。如果我只是得到对应于不同 bin 的频率,那就足够了。另请注意,bin 大小应该是一个变量,就像我提出的解决方案一样。

我已经阅读了这个答案并希望避免循环。我确信有一种更快的方法awk可以绕过for循环。你能帮我一下吗?

Ric*_*lia 7

遵循与我之前的答案相同的算法,我在 awk 中编写了一个非常快的脚本(看图片)。 在此处输入图片说明

脚本如下:

#!/usr/bin/awk -f

BEGIN{
    bin_width=0.1;
    
}
{
    bin=int(($1-0.0001)/bin_width);
    if( bin in hist){
        hist[bin]+=1
    }else{
        hist[bin]=1
    }
}
END{
    for (h in hist)
        printf " * > %2.2f  ->  %i \n", h*bin_width, hist[h]
}
   
Run Code Online (Sandbox Code Playgroud)

bin_width是每个通道的宽度。要使用该脚本,只需将其复制到一个文件中,使其可执行(使用chmod +x <namefile>)并使用./<namefile> <name_of_data_file>.


mou*_*iel 6

对于这个特定问题,我会删除最后一位数字,然后计算排序数据的出现次数:

cut -b1-3 | sort | uniq -c
Run Code Online (Sandbox Code Playgroud)

在指定的输入集上给出:

  2 0.1
  1 0.3
  3 0.4
  1 0.9
Run Code Online (Sandbox Code Playgroud)

输出格式化可以通过这个awk命令来完成:

| awk 'BEGIN{r=0.0}
       {while($2>r){printf "%1.1f-%1.1f %3d\n",r,r+0.1,0;r=r+.1}
       printf "%1.1f-%1.1f %3d\n",$2,$2+0.1,$1}
       END{while(r<0.9){printf "%1.1f-%1.1f %3d\n",r,r+0.1,0;r=r+.1}}'
Run Code Online (Sandbox Code Playgroud)

  • 这就是为什么我从_针对这个特定问题_开始我的回答。问题中的 bin 大小没有变化。 (3认同)