我正在开发一个管道,在某种程度上会以下列格式生成数百个不同的文件(我在我不关心的字段中写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
答案 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]++}...