Найти сумму всех значений, которые перекрываются с несколькими диапазонами perl - PullRequest
0 голосов
/ 18 декабря 2018

У меня есть две файловые структуры:

Интервалы:

chr1    121087394   121087399
chr1    121087820   121087822
chr20   1934714     1934716
chr3    108047283   108047285

Глубина:

chr1 121087395 A 3799
chr1 121087396 T 3818
chr1 121087397 G 3824
chr1 121087398 T 3827
chr1 121087399 G 3831
chr1 121087821 T 2499
chr1 121087822 T 2506
chr20 1934715  G 2650
chr20 1934716  T 2661
chr3 108047284 T 1755
chr3 108047285 C 1750

Я хочу вывод, где столбец 4 является суммойвсе значения из столбца 4 файла глубины попадают в определенный диапазон.Вывод:

    chr1 121087395 121087399 19099
    chr1 121087821 121087822 5005
    chr20 1934715  1934716   5331
    chr3  108047284 108047285 3505

Мой код выглядит следующим образом:

#!/usr/bin/perl
use strict;
use warnings;

my $intervals = $ARGV[0];
my $depth = $ARGV[1];

my $args = $#ARGV+1;


my ($FI, $FD, @F, $i_chr, $i_start, $i_end, @diff, $i, $j);
my $z; 
my $nr=0;
my $sum=0;
open($FI, '<', $intervals) or die "Could not open file: $intervals\n";

while(<$FI>){
    chomp $_;
    ($i_chr, $i_start, $i_end) = split("\t", $_);
    open($FD, '<', $depth) or die "Could not open file: $depth\n";
    while(<$FD>){
    chomp $_;
    @F = split("\t", $_);
    if($F[0] eq $i_chr && $F[1] > $i_start && $F[1] <= $i_end){
        $nr++;
        $sum += $F[3];
    }
    }print "$sum\n";
}

Цикл if не работает.Это печать суммы всех значений столбца 4 файла глубины.

Как я могу изменить этот цикл?

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

Несколько похоже на решение Шона, но вместо хэша массивов я использовал хеш хешей.Кроме того, я не корректировал границы, как Шон сделал с min и max.

#!/usr/bin/perl
use strict;
use warnings;

my %int;
open my $fh, '<', 'f2.txt' or die $!;
# depth file
while (<$fh>) {
    my ($chr, $num, $amt) = (split)[0,1,3];
    $int{$chr}{$num} = $amt;
}
close $fh or die $!;

open $fh, '<', 'f1.txt' or die $!;

# intervals file
while (<$fh>) {
    chomp;
    my ($chr, $start, $stop) = split;

    my $href = $int{$chr}; # hash reference
    my $sum = 0;
    for my $num (keys %$href) {
        if ($start <= $num && $num <= $stop) {
            $sum += $href->{$num};
        }   
    }
    print "$_\t$sum\n";

}
close $fh or die $!;

Результатами этого были:

chr1    121087394   121087399   19099
chr1    121087820   121087822   5005
chr20   1934714     1934716     5311
chr3    108047283   108047284   3505

РЕДАКТИРОВАТЬ: ОП изменил еевходы.Я внес изменения в мою последнюю строку вывода, чтобы отразить это.Она сообщает «5331» в третьей строке аута, но правильный номер - «5311»

0 голосов
/ 18 декабря 2018

Многие цифры в вашем примере вывода не совпадают с вашим описанием того, что вы делаете, и числами в вашем образце ввода - вещи не складываются правильно, числа выходят за пределы диапазона и т. Д., Поэтомулибо ваш пример ввода, вывода или описание неверны, и я не уверен, какой.Кроме того, ваш пример кода не дает ничего похожего на ожидаемый выходной формат (который, как представляется, предназначен для каждого диапазона интервалов, имени, минимальной и максимальной глубины в этом диапазоне и суммы этого последнего столбца)...

Тем не менее, это делает то, что я думаю вы пытаетесь сделать:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say/;
use autodie;

# Read the depths file into a hash table to avoid re-reading it for
# every line of the intervals file.
my %depths;
open my $depth, "<", $ARGV[1];
while (<$depth>) {
  chomp;
  my @F = split /\t/;
  push @{$depths{$F[0]}}, [ $F[1], $F[3] ];
}

open my $intervals, "<", $ARGV[0];
$, = "\t";
while (<$intervals>) {
  chomp;
  my @F = split /\t/;
  my $sum = 0;
  my ($min, $max);
  for my $d (@{$depths{$F[0]}}) {
    if ($d->[0] >= $F[1] && $d->[0] <= $F[2]) {
      $sum += $d->[1];
      $min = $d->[0] if !defined $min || $d->[0] < $min;
      $max = $d->[0] if !defined $max || $d->[0] > $max;
    }
  }
  say $F[0], $min, $max, $sum;
}

Обратите внимание на все, что упомянуто в комментариях zdim: более узкий охватпеременные (что приводит к тому, что предыдущие значения не сохраняются между новыми интервалами) и чтение файла глубины только один раз, а не один раз в строке файла интервалов, что делает его намного более эффективным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...