通过评估过滤爆炸结果,但前提是唯一
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]++}...
我正在开发一个管道,该管道有时会生成数百个以下格式的不同文件(我在我不关心的字段中写了 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]++}...