1

我正在尝试从制表符分隔文件中删除冗余数据,如下所示

chr1    1841    1851    4
chr1    1991    2001    3
chr1    2491    2501    2
chr1    2491    2501    2
chr1    2501    2511    1
chr1    2681    2691    3
chr1    2881    2891    4
chr1    2891    2901    1
chr1    3241    3251    1
chr1    3241    3251    6

条件是:如果前三列相同,则应使用第四列(最大值)中的值来获取前三列和第四列。如果出现平局,则仅应打印 4 列中的值一次。

所以对于上述输入,理想的输出应该是

chr1    1841    1851    4
chr1    1991    2001    3
chr1    2491    2501    2
chr1    2501    2511    1
chr1    2681    2691    3
chr1    2881    2891    4
chr1    2891    2901    1
chr1    3241    3251    6

我是如何接近的:

先对文件进行排序,然后我把它弄乱了

sort file | awk -F '\t' 'NR==1{last = $1; max = 0} {if (last != $1) {printf "%s\t%e\n", last, max; last = $1; max = $4} else if (max < $4) max = $4} END{printf "%s\t%e\n", last, max}'

请帮助

4

4 回答 4

3
$ sort -k1 -k2,3n -k4nr file | awk '!a[$1,$2,$3]++'
chr1    1841    1851    4
chr1    1991    2001    3
chr1    2491    2501    2
chr1    2501    2511    1
chr1    2681    2691    3
chr1    2881    2891    4
chr1    2891    2901    1
chr1    3241    3251    6
于 2013-04-11T09:09:18.137 回答
1

这个单行应该给出输出:

awk -F'\t' -v OFS="\t" '{t=$1FS$2FS$3;if(!(t in a)||a[t]<$4)a[t]=$4}END{for(x in a) print x,a[x]}' file|sort

清晰的格式:

 awk -F'\t' -v OFS="\t" '{
    t=$1FS$2FS$3
    if(!(t in a)||a[t]<$4)
        a[t]=$4
 }
 END{for(x in a) print x,a[x]}' file|sort

如果您使用数据文件运行:

kent$  cat file
chr1    1841    1851    4
chr1    1991    2001    3
chr1    2491    2501    2
chr1    2491    2501    2
chr1    2501    2511    1
chr1    2681    2691    3
chr1    2881    2891    4
chr1    2891    2901    1
chr1    3241    3251    1
chr1    3241    3251    6

kent$  awk -F'\t' -v OFS="\t" '{t=$1FS$2FS$3;if(!(t in a)||a[t]<$4)a[t]=$4}END{for(x in a) print x,a[x]}' file|sort
chr1    1841    1851    4
chr1    1991    2001    3
chr1    2491    2501    2
chr1    2501    2511    1
chr1    2681    2691    3
chr1    2881    2891    4
chr1    2891    2901    1
chr1    3241    3251    6
于 2013-04-11T09:17:50.993 回答
1
sort -k 1,3 -k 4r file | awk 'last != $1" "$2" "$3 { print; last = $1" "$2" "$3; }'

我的输出:

chr1    1841    1851    4
chr1    1991    2001    3
chr1    2491    2501    2
chr1    2501    2511    1
chr1    2681    2691    3
chr1    2881    2891    4
chr1    2891    2901    1
chr1    3241    3251    6

http://ideone.com/nH6boE

于 2013-04-11T08:53:35.317 回答
1

您可以通过使用前三列作为哈希的键来做到这一点,并且只记住具有最大的那一个$4

<infile awk '
  BEGIN { FS = OFS = "\t" }

  $4 > h[$1,$2,$3] { h[$1,$2,$3] = $4 }

  END { 
    for(k in h) { 
      split(k, a, SUBSEP)
      print a[1], a[2], a[3], h[k]
    }
  }
' | sort -k1 -k2n,3n

输出:

chr1    1841    1851    4
chr1    1991    2001    3
chr1    2491    2501    2
chr1    2501    2511    1
chr1    2681    2691    3
chr1    2881    2891    4
chr1    2891    2901    1
chr1    3241    3251    6

如果您使用的是 GNU awk,您还可以在 awk 中进行排序:

解析.awk

BEGIN { FS = OFS = "\t" }

$4 > h[$1,$2,$3] { h[$1,$2,$3] = $4 }

END { 
  len = asorti(h, d)
  for(i=1; i<=len; i++) {
    flen = split(d[i], a, SUBSEP)
    for(j=1; j<=flen; j++)
      printf "%s%s", a[j], OFS
    print h[d[i]]
  }
}

并像这样运行它:

awk -f parse.awk infile
于 2013-04-11T09:07:59.747 回答