Awk - 将列中的值与变量进行比较,计算每个 ID 传递的次数

Awk - 将列中的值与变量进行比较,计算每个 ID 传递的次数

我一直在努力寻找解决方案,但现在我需要一些帮助。

首先,作为输入,我有一个具有以下结构的大文件(5.5G):

scaffold4691_size302    2       T       1
scaffold4691_size302    3       A       1
scaffold4691_size302    4       a       1
scaffold4691_size302    5       a       1
scaffold4691_size302    6       g       2
scaffold4691_size302    7       c       2
scaffold4691_size302    8       c       2
scaffold4692_size187    68      g       4
scaffold4692_size187    69      c       4
scaffold4692_size187    70      a       4
scaffold4692_size187    71      a       4

我想要的是计算第一列($1)的每个ID,第四列($4)中的值大于或等于X(例如玩具模型中的X=4)的次数。

因此,作为输入,我期望:

scaffold4691_size302    0
scaffold4691_size187    4

我可以很容易地在 python 上完成它,因为我对它更舒服,但尺寸太大了。

到目前为止,我这样做了:

awk 'NR>1 { scf=$1; { if ($4>=4){count++;}}} {print scf "\t" count}' toyModel

但它返回了我所有的行和总数。我想知道如何刷新新 ID 的计数。

答案1

您需要累积每个 id 的计数并在处理文件后打印结果:

awk '!counts[$1] { counts[$1] = 0 }; $4 >= 4 { counts[$1]++ }; END { for (key in counts) print key, counts[key] }' toyModel

第一条语句确保我们测量的 id 永远不会匹配标准(最终输出为 0)。第二个增加匹配行的计数。最后一条语句迭代键 (ids) 并打印出键和匹配计数。

如果此方法的大小太大(数组counts变得太大),并且您的 id 在文件中是连续的,则可以改用此方法:

awk 'curid != $1 { if (NR > 1) print curid, count; curid = $1; count = 0 }; $4 >= 4 { count++ }; END { print curid, count }' toyModel

这会保留当前的 ​​id 和计数,并在 id 更改时(以及最后)打印它们。每当第四个字段大于 4 时,计数就会递增,每当 id 更改时,计数就会重置。

答案2

perl -lane '$h{$F[0]} += $F[3] >= 4 ? 1 : 0}{print "$_\t$h{$_}" for keys %h' toyModel

相关内容