在awk中对文本文件进行分组和汇总

时间:2019-02-05 22:40:14

标签: awk

我有一个像这样的文本文件:

示例:

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列。第一列是求和后的数字(从第四列开始),第二列是组名(从第八列开始)。我尝试了以下代码,但未返回我想要的。你知道如何解决吗?

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

这是预期的输出:

预期输出:

160 CDK4
57  NUP107
81  IKBIP
646 TXNRD1

3 个答案:

答案 0 :(得分:4)

$ 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

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

使用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

$