通过评估过滤爆炸结果,但前提是唯一

Filtering blast results by evalue but only if unique

我正在开发一个管道,该管道有时会生成数百个以下格式的不同文件(我在我不关心的字段中写了 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,根据评估值(越小越好)取最佳结果,但如果最佳评估值重复使用相同的 ID,则不计算该 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 的最佳评估值不是唯一的,因此不存储 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

awk 救援!

awk '!( in min) || <min[] {min[]=; line[]=[=10=]} 
     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[]++'

 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 '!( in min) || <=min[] {min[]=; line[]=[=12=]; c[,]++}
    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)。例如

... +0<=min[] {min[]=+0; line[]=[=13=]; c[,+0]++}...