通过evalue过滤爆破结果,但仅限于唯一

时间:2017-04-06 18:35:28

标签: bash awk blast

我正在开发一个管道,在某种程度上会以下列格式生成数百个不同的文件(我在我不关心的字段中写X):

 id1   X   X   X   X   X   X   X   X   X  evalue1   X
 id2   X   X   X   X   X   X   X   X   X  evalue2   X     
 ...

我必须过滤此文件,对于每个ID,根据evalue获取最佳结果(越小越好)但如果使用相同ID重复最佳evalue,则不计算该ID。

例如,如果输入文件是:

 id1   X   X   X   X   X   X   X   X   X  3e-07   X
 id1   X   X   X   X   X   X   X   X   X  3e-04   X
 id2   X   X   X   X   X   X   X   X   X  3e-07   X     
 id3   X   X   X   X   X   X   X   X   X  3e-04   X     
 id3   X   X   X   X   X   X   X   X   X  3e-04   X     
 id3   X   X   X   X   X   X   X   X   X  1e-02   X     

预期输出为:

 id1   X   X   X   X   X   X   X   X   X  3e-07   X
 id2   X   X   X   X   X   X   X   X   X  3e-07   X     

在id1的两个匹配之间,最坏的被删除,因为id3最佳evalue不是唯一的ID,不存储ID。

我尝试过使用blast命令行工具,但是最接近的选项是将最大命中数设置为1,但是像id3这样的情况仍保留在输出中。所以我的解决方案是一个python脚本,但文件数量使这个过程非常耗时。

有没有办法用bash工具(awk?)过滤这些文件才足够有效?

每个文件都有唯一标识符,因此相同的ID不能出现在多个文件中。

提前致谢

更新1:

此处为示例文件:

 D00733:159:CA65UANXX:8:1104:7340:77245  gi|13507739|ref|NC_000912.1|    100.00  24      0       0       1       24      529212  529189  3e-07   44.6
 D00733:159:CA65UANXX:8:2303:18019:72377 gi|13507739|ref|NC_000912.1|    100.00  20      0       0       1       20      622755  622736  2e-05   37.4
 D00733:159:CA65UANXX:8:2103:11030:25200 gi|13507739|ref|NC_000912.1|    95.24   21      1       0       1       21      321813  321833  3e-04   33.7
 D00733:159:CA65UANXX:8:2103:11030:25200 gi|13507739|ref|NC_000912.1|    95.24   21      1       0       1       21      495963  495943  3e-04   33.7
 D00733:159:CA65UANXX:8:2103:11030:25200 gi|13507739|ref|NC_000912.1|    95.00   20      1       0       2       21      613871  613852  0.001   31.9

使用@karafka建议的解决方案后,输出为:

 D00733:159:CA65UANXX:8:2303:18019:72377 gi|13507739|ref|NC_000912.1|   100.00  20  0   0   1   20  622755  622736  2e-05   37.4
 D00733:159:CA65UANXX:8:2103:11030:25200 gi|13507739|ref|NC_000912.1|   95.00   20  1   0   2   21  613871  613852  0.001   31.9
 D00733:159:CA65UANXX:8:1104:7340:77245  gi|13507739|ref|NC_000912.1|   100.00  24  0   0   1   24  529212  529189  3e-07   44.6

似乎最后一个id最少需要0.001。

我正在使用GNU Awk 3.1.5

更新2

执行数字转换并不能解决awk 3.1.5中的问题,只有解决方案:将awk更新为> = 3.1.8

1 个答案:

答案 0 :(得分:3)

awk救援!

awk '!($1 in min) || $11<min[$1] {min[$1]=$11; line[$1]=$0} 
     END {for(k in line) print line[k]}' file

 id1   X   X   X   X   X   X   X   X   X  3e-07   X
 id2   X   X   X   X   X   X   X   X   X  3e-07   X
 id3   X   X   X   X   X   X   X   X   X  3e-04   X

这不取决于条目的顺序,但也不保证输出顺序。

sort辅助

的另一种解决方案
sort -k1,1 -k11g file | awk '!a[$1]++'

 id1   X   X   X   X   X   X   X   X   X  3e-07   X
 id2   X   X   X   X   X   X   X   X   X  3e-07   X
 id3   X   X   X   X   X   X   X   X   X  3e-04   X

仅在最小值为唯一时才打印

awk '!($1 in min) || $11<=min[$1] {min[$1]=$11; line[$1]=$0; c[$1,$11]++}
    END {for(k in line) if(c[k,min[k]]==1) print line[k]}' file

 id1   X   X   X   X   X   X   X   X   X  3e-07   X
 id2   X   X   X   X   X   X   X   X   X  3e-07   X

要强制执行数字转换,您可以将0添加到值($ 11)。例如

... $11+0<=min[$1] {min[$1]=$11+0; line[$1]=$0; c[$1,$11+0]++}...