优化大数据相交

时间:2014-07-28 17:30:21

标签: perl

我有两个文件,子集看起来像这样:

区域

chr1    150547262       150547338       v2MCL1_29.1.122 .       GENE_ID=MCL1;Pool=2;PURPOSE=CNV
chr1    150547417       150547537       v2MCL1_29.1.283 .       GENE_ID=MCL1;Pool=1;PURPOSE=CNV
chr1    150547679       150547797       v2MCL1_29.2.32  .       GENE_ID=MCL1;Pool=2;PURPOSE=CNV
chr1    150547866       150547951       v2MCL1_29.2.574 .       GENE_ID=MCL1;Pool=1;PURPOSE=CNV
chr1    150548008       150548096       v2MCL1_29.2.229 .       GENE_ID=MCL1;Pool=2;PURPOSE=CNV
chr4    1801108 1801235 v2FGFR3_3.11.182        .       GENE_ID=FGFR3;Pool=2;PURPOSE=CNV
chr4    1801486 1801615 v2FGFR3_3.11.202        .       GENE_ID=FGFR3;Pool=1;PURPOSE=CNV
chrX    66833436        66833513        v2AR_region.70.118      .       GENE_ID=AR;Pool=1;PURPOSE=CNV
chrX    66866117        66866228        v2AR_region.103.68      .       GENE_ID=AR;Pool=2;PURPOSE=CNV
chrX    66871579        66871692        v2AR_region.108.32      .       GENE_ID=AR;Pool=1;PURPOSE=CNV

注意:字段1来自chr1..chrX

查询(有点标准的VCF文件)

1       760912  .       C       T       21408   PASS    .       GT:DP:GQ:PL     1/1:623:99:21408,1673,0
1       766105  .       T       A       11865   PASS    .       GT:DP:GQ:PL     1/1:618:99:11865,1025,0
1       767780  .       G       A       15278   PASS    .       GT:DP:GQ:PL     1/1:512:99:15352,1274,74
1       150547747       .       G       A       9840    PASS    .       GT:DP:GQ:PL     0/1:645:99:9840,0,9051
1       204506107       .       C       T       22929   PASS    .       GT:DP:GQ:PL     1/1:636:99:22929,1801,0
1       204508549       .       T       G       22125   PASS    .       GT:DP:GQ:PL     1/1:638:99:22125,1757,0
2       2765262 .       A       G       22308   PASS    .       GT:DP:GQ:PL     1/1:678:99:22308,1854,0
2       2765887 .       C       T       9355    PASS    .       GT:DP:GQ:PL     0/1:649:99:9355,0,9235
2       25463483        .       G       A       31041   PASS    .       GT:DP:GQ:PL     1/1:936:99:31041,2422,0
2       212578379       .       TA      T       5355    PASS    .       GT:DP:GQ:PL     0/1:500:99:5355,0,3249
3       178881270       .       T       G       10012   PASS    .       GT:DP:GQ:PL     0/1:632:99:10012,0,7852
3       182673196       .       C       T       31170   PASS    .       GT:DP:GQ:PL     1/1:896:99:31170,2483,0
4       1801511 .       C       T       12218   PASS    .       GT:DP:GQ:PL     0/1:885:99:12218,0,11568
4       55097835        .       G       C       7259    PASS    .       GT:DP:GQ:PL     0/1:512:99:7259,0,7099
4       55152040        .       C       T       15866   PASS    .       GT:DP:GQ:PL     0/1:1060:99:15866,0,14953
X       152017752       .       G       A       9786    PASS    .       GT:DP:GQ:PL     0/1:735:99:9786,0,11870
X       152018832       .       T       G       12281   PASS    .       GT:DP:GQ:PL     0/1:924:99:12281,0,13971
X       152019715       .       A       G       10128   PASS    .       GT:DP:GQ:PL     0/1:689:99:10128,0,9802

注意:有几个前导线组成标题,并以'#'开头。炭。

我正在尝试编写一个脚本,该脚本将使用查询文件的前两个字段来查看坐标是否位于区域文件的第二个和第三个字段之间。我把它编码为:

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

use Data::Dump;

my $bed = shift;
my $query_file = shift;

my %regions;
open( my $region_fh, "<", $bed ) || die "Can not open the input regions BED file: $!";
while (<$region_fh>) {
    next if /track/;
    my @line = split;
    $line[0] =~ s/chr//; # need to strip of 'chr' or won't match query file
    my ($gene, $pool, $purpose) = $line[5] =~ /GENE_ID=(\w+);(Pool=\d+);PURPOSE=(.*)$/;
    @{$regions{$line[3]}} = (@line[0..4],$gene,$pool,$purpose);
}
close $region_fh;

my ( @header, @results );
open( my $query_fh, "<", $query_file ) || die "Can not open the query file: $!";
while (<$query_fh>) {
    if ( /^#/ ) {
        push( @header, $_ );
        next;
    }
    my @fields = split;
    for my $amp ( keys %regions ) {
        if ( $fields[0] eq $regions{$amp}->[0] && $fields[1] >= $regions{$amp}->[1] && $fields[1] <= $regions{$amp}->[2] ) {
            $fields[2] = $regions{$amp}->[5]; # add gene name to VCF file
            push( @results, join( "\t", @fields ) );
        }
    }
}
close $query_fh;

问题是查询文件长约325万行,而区域文件长约2500行。因此,运行这需要很长时间(我在等待大约20分钟后退出)。

我认为我的整体逻辑是正确的(希望如此!),我想知道是否有办法优化数据的处理方式,以加快处理所需的时间。我认为问题是我需要在2500 * 325万次的区域内遍历阵列。任何人都可以提供有关如何修改我的算法以更有效地处理这些数据的任何建议吗?

编辑:添加了一个更大的样本数据集,这次应该显示一些正数。

1 个答案:

答案 0 :(得分:3)

我能想到两种方法。第一种是将%regions的键更改为染色体名称,其值是与该染色体对应的所有起始,结束和基因ID值的列表,按起始值排序。

使用您的新数据,哈希看起来像这样

(
  chr1 => [
            [150547262, 150547338, "MCL1"],
            [150547417, 150547537, "MCL1"],
            [150547679, 150547797, "MCL1"],
            [150547866, 150547951, "MCL1"],
            [150548008, 150548096, "MCL1"],
          ],
  chr4 => [
            [1801108, 1801235, "FGFR3"],
            [1801486, 1801615, "FGFR3"]
          ],
  chrX => [
            [66833436, 66833513, "AR"],
            [66866117, 66866228, "AR"],
            [66871579, 66871692, "AR"],
          ],
)

这样,染色体名称可以立即对哈希的右边部分进行访问,而不必每次都搜索每个条目,并且排序的起始值允许二进制搜索。

另一种可能性是将整个regions文件写入SQLite临时内存数据库。一旦数据被存储和索引,查找给定染色体和位置的基因ID将非常快。