首页 > 解决方案 > 使用 awk 计算行组数

问题描述

我有一个数据集:(file.txt)

X    Y
1    a
2    b
3    c
10   d
11   e
12   f
15   g
20   h     
25   i
30   j
35   k
40   l
41   m
42   n
43   o
46   p

我想添加两列,分别是 Up10 和 Down10,

例如:

X    Y    Up10    Down10    
35   k     3        5  

期望的输出:

X    Y    Up10    Down10
1    a     1        5
2    b     2        5
3    c     3        4
10   d     4        5
11   e     5        4
12   f     5        3
15   g     4        3
20   h     5        3
25   i     3        3
30   j     3        3
35   k     3        5
40   l     3        5
41   m     3        4
42   n     4        3
43   o     5        2
46   p     5        1

这是 Pierre François 的解决方案:再次感谢@Pierre François

awk '
BEGIN{OFS="\t"; print "X\tY\tUp10\tDown10"}
(NR == FNR) && (FNR > 1){a[$1] = $1 + 0}
(NR > FNR) && (FNR > 1){ 
  up = 0; upl = $1 - 10
  down = 0; downl = $1 + 10
  for (i in a) { i += 0 # tricky: convert i to integer
    if ((i >= upl) && (i <= $1)) {up++}
    if ((i >= $1) && (i <= downl)) {down++}
  }
  print $1, $2, up, down;
}
' file.txt file.txt > file-2.txt

但是当我使用这个命令来处理 13GB 的数据时,它需要的时间太长了。

我再次使用这种方式处理 13GB 数据:

awk 'BEGIN{ FS=OFS="\t" }
NR==FNR{a[NR]=$1;next} {x=y=FNR;while(--x in a&&$1-10<a[x]){} while(++y in a&&$1+10>a[y]){} print $0,FNR-x,y-FNR}
' file.txt file.txt > file-2.txt

当 file-2.txt 达到 1.1GB 时,它会被冻结。我等了几个小时,但我看不到命令​​和最终输出文件的完成。

注意:我正在研究 Gogole 云。机器类型 e2-highmem-8(8 个 vCPU,64 GB 内存)

标签: awk

解决方案


一个单次 awk 保持 10 个最后记录的滑动窗口并使用它来计算起伏。为了对称起见,应该有deletesEND但我猜内存中的一些额外的数组元素不会有所作为:

$ awk '
BEGIN {
    FS=OFS="\t"
}
NR==1 {
    print $1,$2,"Up10","Down10"
}
NR>1 {
    a[NR]=$1
    b[NR]=$2

    for(i=NR-9;i<=NR;i++) {
        if(a[i]>=a[NR]-10&&i>=2)
            up[NR]++
        if(a[i]<=a[NR-9]+10&&i>=2)
            down[NR-9]++
    }
}
NR>10 {
    print a[NR-9],b[NR-9],up[NR-9],down[NR-9]
    delete a[NR-9]
    delete b[NR-9]
    delete up[NR-9]
    delete down[NR-9]
}
END {
    for(nr=NR+1;nr<=NR+9;nr++) {
        for(i=nr-9;i<=nr;i++)
            if(a[i]<=a[nr-9]+10&&i>=2&&i<=NR)
                down[nr-9]++
        print a[nr-9],b[nr-9],up[nr-9],down[nr-9]
   }
}' file

输出:

X       Y       Up10    Down10
1       a       1       5
2       b       2       5
...
35      k       3       5
...
43      o       5       2
46      p       5       1

推荐阅读