AWK:以用户定义的块大小划分列;并对每个块的每个条目进行计数+求和;给出所有块的每个条目的平均值

AWK:以用户定义的块大小划分列;并对每个块的每个条目进行计数+求和;给出所有块的每个条目的平均值

我需要帮助来通过 awk 处理列条目。以下是我想尝试的操作:

  • 以用户定义的块大小划分列;
  • 计算并总结每个块的每个条目,最终得出每个条目的平均值,即最终的块大小。

例如,下面是一个列表:

1
2
3
4
5
6
7
8
9
10
11
12

在这里,我想使用 4 的块大小(但在我的情况下,它可能因情况而异):

  • 块1
    1
    2
    3
    4
    
  • 块2
    5
    6
    7
    8
    
  • 块3
    9
    10
    11
    12
    

处理后,我想要:

5
6
7
8

这是所有块中位置 1、2、3 和 4 的条目的平均值。

答案1

下面的awk程序可以完成这项工作。它假设数据存储data.txt在第一列中(但可以轻松地适应任何其他列)。它还假设没有空列,只有完整的块。

awk -v cs=4 '{if ((i=NR%cs)==0) {n_ch++; i=cs};buf[i]+=$1;} END{for (i=1;i<=cs;i++) printf "%d\n",buf[i]/n_ch}' data.txt

awk块大小通过语句传递。-v cs=size

对于每一行,它将确定“块内的条目号”,i通过 i = "line number" modulo "chunk size",并将条目求和到一个数组中buf。每当一个块完成时,块计数器n_ch就会增加。

最后,我们打印所有条目数的平均值。

答案2

awk -v cs=4 '
  BEGIN {
    "(wc -l <" ARGV[1] ")" | getline nl
    nc = sprintf("%d", nl/cs)
  }
  { a[NR%cs] += $1 }
  NR>nl-cs { print a[NR%cs]/nc } 
' file
5
6
7
8
  • 在 begin 块中,我们确定文件中的行并将其存储在 nl 变量中。
  • 然后我们得到块的数量并将其存储在 nc 变量中。
  • 将运行总和累加到以行号 % 块大小为模数索引的数组中。
  • 然后,当行号超过 nl-cs 的阈值时,意味着我们正在进入最后一个块,我们开始打印结果。

或者,如果我们不想预先计算文件长度和块数,我们可以这样做:

awk -v cs=4 '
  { a[NR] = $1 }
  END {
    for (i=1; i<=cs; i++) {
      k = s = 0
      for (j=i; j<=NR; j+=cs) {
        s += a[j]; k++
      }
      print s/k
    }
  }
' file

答案3

另一种方法awk是在运行过程中对每个块中的元素进行计数,因此如果记录计数不是精确的块倍数,这并不重要,它仍然是平均值

awk -v ch=4 '{k=(NR-1)%ch; n[k]++; un[k]+=$1}
  END{for (k in un) print "Line "k+1" has "n[k]" elements totalling "un[k]" and average "un[k]/n[k]}' file

Line 1 has 3 elements totalling 15 and average 5
Line 2 has 3 elements totalling 18 and average 6
Line 3 has 3 elements totalling 21 and average 7
Line 4 has 3 elements totalling 24 and average 8

虽然END不必是描述性的

  END{for (k in un) print un[k]/n[k]}' file

5
6
7
8

如果你想保证输出顺序

  END{for (k=0; k<ch; k++) print un[k]/n[k]}' file

相关内容