perl – 从文件中获取属于其他文件中的区域的区域(无循环)

前端之家收集整理的这篇文章主要介绍了perl – 从文件中获取属于其他文件中的区域的区域(无循环)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有两个文件

regions.txt:第一列是染色体名称,第二列是开始和结束位置.

  1. 1 100 200
  2. 1 400 600
  3. 2 600 700

coverage.txt:第一列是染色体的名字,再第二和第三的开始和结束位置,而最后一列是得分.

  1. 1 100 101 5
  2. 1 101 102 7
  3. 1 103 105 8
  4. 2 600 601 10
  5. 2 601 602 15

这个文件非常庞大,大约15GB,大约有3亿行.

我基本上想得到coverage.txt中所有得分的均值,这些得分位于regions.txt中的每个区域.

换句话说,开始在regions.txt第一行中,如果在一个coverage.txt线,其具有在相同的染色体上,启动覆盖是&GT =启动区,和最终的覆盖为< =最终区域,然后将其得分保存到新阵列.经过所有coverages.txt完成搜索打印区域染色体,开始,结束,并已发现所有得分的平均值. 预期产量:

  1. 1 100 200 14.6 which is (5+7+8)/3
  2. 1 400 600 0 no match at coverages.txt
  3. 2 600 700 12.5 which is (10+15)/2

我内置了以下MATLAB脚本,因为我不得不遍历coverage.txt很多时间,这需要很长的时间.我不知道如何制作一个快速awk类似的脚本.

我的matlab脚本

  1. fc = fopen('coverage.txt','r');
  2. ft = fopen('regions.txt','r');
  3. fw = fopen('out.txt','w');
  4.  
  5. while feof(ft) == 0
  6.  
  7. linet = fgetl(ft);
  8. scant = textscan(linet,'%d%d%d');
  9. tchr = scant{1};
  10. tx = scant{2};
  11. ty = scant{3};
  12. coverages = [];
  13.  
  14. frewind(fc);
  15. while feof(fc) == 0
  16.  
  17. linec = fgetl(fc);
  18. scanc = textscan(linec,'%d%d%d%d');
  19. cchr = scanc{1};
  20. cx = scanc{2};
  21. cy = scanc{3};
  22. cov = scanc{4};
  23.  
  24.  
  25. if (cchr == tchr) && (cx >= tx) && (cy <= ty)
  26.  
  27. coverages = cat(2,coverages,cov);
  28.  
  29. end
  30.  
  31. end
  32.  
  33. covmed = median(coverages);
  34. fprintf(fw,'%d\t%d\t%d\t%d\n',tchr,tx,ty,covmed);
  35.  
  36. end

任何建议使用AWK,Perl中,使替代或…等我将ASLO很高兴,如果有人可以教我如何摆脱所有循环的在我的MATLAB程序.

谢谢

解决方法

这是一个Perl解决方案.我使用哈希(aka dictionaries)通过染色体访问各种范围,从而减少循环迭代次数.

这可能是有效的,因为我没有对每个输入行上的regions.txt进行完整循环.使用多线程时,效率可能会进一步提高.

  1. #!/usr/bin/perl
  2.  
  3. my ($rangefile) = @ARGV;
  4. open my $rFH,'<',$rangefile or die "Can't open $rangefile";
  5.  
  6. # construct the ranges. The chromosome is used as range key.
  7. my %ranges;
  8. while (<$rFH>) {
  9. chomp;
  10. my @field = split /\s+/;
  11. push @{$ranges{$field[0]}},[@field[1,2],0];
  12. }
  13. close $rFH;
  14.  
  15. # iterate over all the input
  16. while (my $line = <STDIN>) {
  17. chomp $line;
  18. my ($chrom,$lower,$upper,$value) = split /\s+/,$line;
  19. # only loop over ranges with matching chromosome
  20. foreach my $range (@{$ranges{$chrom}}) {
  21. if ($$range[0] <= $lower and $upper <= $$range[1]) {
  22. $$range[2]++;
  23. $$range[3] += $value;
  24. last; # break out of foreach early because ranges don't overlap
  25. }
  26. }
  27. }
  28.  
  29. # create the report
  30. foreach my $chrom (sort {$a <=> $b} keys %ranges) {
  31. foreach my $range (@{$ranges{$chrom}}) {
  32. my $value = $$range[2] ? $$range[3]/$$range[2] : 0;
  33. printf "%d %d %d %.1f\n",$chrom,@$range[0,1],$value;
  34. }
  35. }

示例调用

  1. $perl script.pl regions.txt <coverage.txt >output.txt

示例输入的输出

  1. 1 100 200 6.7
  2. 1 400 600 0.0
  3. 2 600 700 12.5

(因为(5 7 8)/ 3 = 6.66 …)

猜你在找的Perl相关文章