【问题标题】:grouping and summarizing a text file in awk在 awk 中对文本文件进行分组和汇总
【发布时间】:2019-02-06 21:55:26
【问题描述】:

我有一个类似这个例子的文本文件:

示例:

chr12   58146000    58146050    79  chr12   58145961    58146075    CDK4
chr12   58146050    58146075    81  chr12   58145961    58146075    CDK4
chr12   69082750    69082800    57  chr12   69082741    69082833    NUP107
chr12   99038450    99038479    81  chr12   99038300    99038479    IKBIP
chr12   104680862   104680887   512 chr12   104680862   104680887   TXNRD1
chr12   104682708   104682750   134 chr12   104682708   104682818   TXNRD1

我想根据第 8 列对它们进行分组,并对属于同一组的第 4 列的值求和,结果将是一个包含 2 列的制表符分隔文件。第一列是求和后的数字(来自第 4 列),第 2 列是组名(来自第 8 列)。我尝试了以下代码,但它没有返回我想要的。你知道怎么解决吗?

cut -d'\t' -f 8 | sort | uniq -c | awk '{ print sum($4), $8 }' infile > outfile

这是预期的输出:

预期输出:

160 CDK4
57  NUP107
81  IKBIP
646 TXNRD1

【问题讨论】:

    标签: awk


    【解决方案1】:
    $ awk -v OFS='\t' '{sum[$8]+=$4} END{for (grp in sum) print sum[grp], grp}' file
    81      IKBIP
    57      NUP107
    646     TXNRD1
    160     CDK4
    

    【讨论】:

    • nit:问题指定“制表符分隔文件”作为输出,所以我会推荐 awk ... OFS=\\t 而不是管道到 column -t
    • 最终添加| sort -k2 以与问题中要求的顺序相同,或者可能是asorti?在 GNU 上下文中。
    • @Allan 对输出进行排序不会产生问题中显示的顺序。如果 OP 想要一个特定的输出顺序,它可能与输入的顺序相同,而不是对输出进行排序,这在 awk 脚本中很简单,再次 IF 是必要的。
    【解决方案2】:

    另一种方法,使用GNU datamash 代替 awk:

    $ datamash -s groupby 8 sum 4 < data.tsv | datamash reverse
    160 CDK4
    81  IKBIP
    57  NUP107
    646 TXNRD1
    

    这假设输入文件中的列也是制表符分隔的。如果不是,请将-W 添加到选项中。

    【讨论】:

      【解决方案3】:

      使用perl的另一种方法

       perl -lane ' $kv{$F[7]}+=$F[3]; END { for(keys %kv) { print "$_\t$kv{$_}" }} '
      

      使用给定的输入

      $ cat elly.txt
      chr12   58146000    58146050    79  chr12   58145961    58146075    CDK4
      chr12   58146050    58146075    81  chr12   58145961    58146075    CDK4
      chr12   69082750    69082800    57  chr12   69082741    69082833    NUP107
      chr12   99038450    99038479    81  chr12   99038300    99038479    IKBIP
      chr12   104680862   104680887   512 chr12   104680862   104680887   TXNRD1
      chr12   104682708   104682750   134 chr12   104682708   104682818   TXNRD1
      
      $ perl -lane ' $kv{$F[7]}+=$F[3]; END { for(keys %kv) { print "$_\t$kv{$_}" }} ' elly.txt
      NUP107  57
      TXNRD1  646
      IKBIP   81
      CDK4    160
      
      $
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-03
        • 2021-10-16
        • 1970-01-01
        • 1970-01-01
        • 2017-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多