我有一个带范围的文件。我想要列表中的最高范围,并删除其他小的重叠范围:
chr1A 77568 86766
chr1A 203138 204427
chr1A 204428 222994
chr1A 204428 206534
chr1A 206538 207965
chr1A 207967 213097
chr1A 213098 221111
chr1A 213098 213863
chr1A 213864 214195
chr1A 214196 221111
chr1A 221112 222994
chr1A 222995 223876
chr1A 223882 227109
chr1A 305432 314629
chr1A 323643 325976
chr1A 431741 451601
chr1A 431741 435137
chr1A 435141 436568
chr1A 436570 441700
chr1A 441701 449710
chr1A 441701 442466
chr1A 442467 442798
chr1A 442799 449710
chr1A 449711 451601
例如:
第一个和第二个范围是唯一的,因此保留它们。
第3至第11个范围重叠,仅保留最高的chr1A 204428 222994
,依此类推。
我想要这样的输出:
chr1A 77568 86766
chr1A 203138 204427
chr1A 204428 222994
chr1A 222995 223876
chr1A 223882 227109
chr1A 305432 314629
chr1A 323643 325976
chr1A 431741 451601
我希望在perl,bash或任何其他unix工具中获得解决方案。谢谢
答案 0 :(得分:0)
这是蛮力方法的一个例子。对于每个间隔,我们检查它是否包含在其他任何间隔中。不用说,根据数据量(输入文件中的行数),这可能会变得很慢:
use feature qw(say);
use strict;
use warnings;
my $fn = 'input.txt';
open ( my $fh, '<', $fn ) or die "Could not open file '$fn': $!";
my @ranges;
while (my $line = <$fh> ) {
chomp $line;
my ( $chr, $low, $high ) = split " ", $line;
push @ranges, {chr => $chr, range => [$low, $high]};
}
close $fh;
my @result;
RANGE: for my $i (0..$#ranges) {
my ( $low, $high ) = @{ $ranges[$i]->{range} };
for my $j (0..$#ranges) {
next if $i == $j;
my ($low2, $high2) = @{ $ranges[$j]->{range} };
next RANGE if $low>= $low2 && $high<= $high2;
}
push @result, $ranges[$i];
}
for my $range (@result) {
say join "\t", $range->{chr}, @{ $range->{range} };
}
输出:
chr1A 77568 86766
chr1A 203138 204427
chr1A 204428 222994
chr1A 222995 223876
chr1A 223882 227109
chr1A 305432 314629
chr1A 323643 325976
chr1A 431741 451601