【问题标题】:How to use awk to only print matches that have the minimum value at a certain field?如何使用 awk 仅打印在某个字段具有最小值的匹配项?
【发布时间】:2019-07-01 00:06:09
【问题描述】:

我正在尝试解析 HMMER 给出的一些结果,并且在 tblout 文件中我能够隔离我想要的匹配项。

尽管如此,如果相同的值只匹配一个配置文件,则会重复多次。

例如,这是一次读取重复 3 次:

SRR6033660.161030 FAM007172 4e-15 4.2e-15 63.4 63.4
SRR6033660.1458607 FAM019859 2.5e-12 2.7e-12 55.0 54.9
SRR6033660.1458607 FAM015326 4e-14 4.2e-14 58.8 58.7
SRR6033660.1458607 FAM000764 7.5e-25 8.1e-25 94.6 94.5

它匹配 3 个家庭,但我只想选择具有最低 e 值的行(第 3 列和第 4 列)

我如何编写一个 awk 命令来给我这个输出?

SRR6033660.161030 FAM007172 4e-15 4.2e-15 63.4 63.4
SRR6033660.1458607 FAM000764 7.5e-25 8.1e-25 94.6 94.5

谢谢!

【问题讨论】:

  • 如果您有 A 行和 B 行且 A1==B1 其中 A3>B3 但 B4>A4,您想要什么?
  • edit你的问题,向我们展示你到目前为止所做的尝试。

标签: awk minimum


【解决方案1】:

选择两个字段的最小值通常不会起作用,这里我提出了一个线性组合,您可以在其中设置权重。

$ awk -v a=0.5 '{c=a*$3+(1-a)*$4}
        !($1 in min) || c<min[$1]{min[$1]=c; minLine[$1]=$0}
         END{for(k in minLine) print minLine[k]}' file | column -t

SRR6033660.1458607  FAM000764  7.5e-25  8.1e-25  94.6  94.5
SRR6033660.161030   FAM007172  4e-15    4.2e-15  63.4  63.4

由于散列,不保留记录的顺序。您可以添加一个序列号,然后根据它进行排序。

【讨论】:

    【解决方案2】:

    这是 $3$4 的总和,总和最小的一个具有最低的 e 值(在没有更好的定义的情况下):

    $ awk '
    # $3+$4==s[$1] {            # this commented out part appends records when
    #    r[$1]=r[$1] ORS $0     # the sum of $3+$4 is equally small with the 
    # }                         # smallest so far
    $3+$4<s[$1] || s[$1]=="" {  # if the sum of $3+$4 is the smallest or first
        s[$1]=$3+$4             # store the sum
        r[$1]=$0                # and record
    }
    END {                       # after all records are processed
        for(i in r)             # loop thru stored records
            print r[i]          # and output them
    }' file
    SRR6033660.1458607 FAM000764 7.5e-25 8.1e-25 94.6 94.5
    SRR6033660.161030 FAM007172 4e-15 4.2e-15 63.4 63.4
    

    如果取消注释第一个块,脚本将输出所有具有最小$3+$4 的记录,例如:awk {script} file file 将输出:

    SRR6033660.1458607 FAM000764 7.5e-25 8.1e-25 94.6 94.5
    SRR6033660.1458607 FAM000764 7.5e-25 8.1e-25 94.6 94.5
    SRR6033660.161030 FAM007172 4e-15 4.2e-15 63.4 63.4
    SRR6033660.161030 FAM007172 4e-15 4.2e-15 63.4 63.4
    

    【讨论】:

      【解决方案3】:

      其他人提供了纯 awk 解决方案。请注意,它们实际上涉及将数据的全部内容加载到内存中。这在一般情况下是有问题的。

      事实证明,排序(特别是 GNU coreutils 版本,不确定其他版本)足够聪明,可以在处理大量数据时使用临时文件。它还可以比较浮点数指定的数字。

      所以:

      LC_NUMERIC=C sort <TBLOUT -k1 -k3g -k4g | awk 't!=$1{t=$1;print}'
      
      • 首先,对输入进行排序,使行按第一列分组,然后按第 3 列和第 4 列进行数字排序
      • LC_NUMERIC=C 确保我们在数字写为 1.234,56 而不是 1,234.56 的语言环境中正确排序
      • 如果第 4 列更重要,我们可以切换 -k3g-k4g
      • 没有简单的方法来组合/加权第 3 列和第 4 列(但我们可以预处理每一行以生成一个新列 - 可能在排序之前通过另一个 awk 管道)
      • 管道结果到 awk - 仅打印第一列已更改的行

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-29
        • 2015-02-04
        • 2011-02-26
        • 2010-12-16
        相关资源
        最近更新 更多