比较两个表和基于身份的过滤器

时间:2014-09-03 09:33:17

标签: perl

我在编写脚本时遇到一些麻烦,该脚本遍历两个不同的表并根据身份过滤行。我只是意识到这可能超出了我对perl的了解,所以我希望我能从你们那里得到一些方便的提示!

我有两个制表符分隔的表格,如下所示:

alleles.txt:

chr     pse.bp  bp      nalleles        maf     acc-1   acc-2   acc-3   acc-4    acc-5   acc-6    acc-7    acc-8   acc-9    acc-10    acc11    acc12    acc13 acc14    acc15
1       11      11      2       18      T       T       T       T       T       T       T       T       T       T       T       T       T       T       C       T
1       18      18      2       18      T       T       T       T       T       T       T       T       T       T       T       T       T       T       C       T
1       22      21.5    3       16      0       0       0       T       0       0       0       0       0       0       T       TCCTAAAT        0       0       0

hmp.txt:

rs#     alleles chrom   pos     strand  assembly#       center  protLSID        assayLSID       panelLSID       QCcode  M.10        M.101       M.103
NA      NA      1       10971981        NA      NA      NA      NA      NA      NA      NA      2       1       2
NA      NA      1       11716572        NA      NA      NA      NA      NA      NA      NA      1       1       1

我想编写一个脚本来处理这些数据:

我需要来自alleles.txt的信息,但我不需要每一行。我希望程序取第一行alleles.txt,如果它在hmp.txt中找到一行,其中alleles.txt的第一列与hmp.txt的第三列匹配,而alleles.txt的第三列匹配hmp.txt的第四列,它应该将此行写入新文件。我想对allels.txt中的每一行做。 我尝试使用嵌套的while循环执行此操作,这是我到目前为止尝试运行的代码:

#!/usr/bin/perl
# maghap.pl
# converts pre-processed alleles layout into TASSEL-readable hapmap format.
# type ./maghap.pl hmp.txt alleles.txt to use this program.
use strict;#use warnings;

die "usage: ./maghap.pl RSB.lars.hmp.txt alleles.txt\n" unless (@ARGV == 2);
#open(my $hapmap, "<", "$ARGV[0]") or die "ERROR loading $ARGV[0]\n";
open(my $alleles, "<", "$ARGV[1]") or die "ERROR loading $ARGV[1]\n";
open(my $out, ">", "$ARGV[1].realsnps") or die "ERROR creating $ARGV[1].realsnps\n";

while (my $allelesline = <$alleles>) {
  #chomp;
  my @alleles_columns = split (/\t/, $allelesline);
  #print $out "@alleles_columns";
  #my $hit = 0;
  open(my $hapmap, "<", "$ARGV[0]") or die "ERROR loading $ARGV[0]\n";
  while (my $hapmapline = <$hapmap>) {
  #chomp;
    my @hapmap_columns = split(/\t/, $hapmapline);
    #print $out "@hapmap_columns";
    if ($alleles_columns[0] == $hapmap_columns[2]) {
      if ($alleles_columns[2] == $hapmap_columns[3]) {
        print $out "@alleles_columns";
        #print $out "@hapmap_columns";
        #$hit = 1;
        last;
      }
    }
  #print $out "@alleles_columns" if $hit;
  }
  close $hapmap;
}
#close $hapmap;
close $alleles;
close $out;

正如你可以看到的所有评论线,我试了很多东西,但似乎我现在被卡住了...... 到目前为止,该程序至少运行但由于某种原因它找不到任何匹配(有匹配,我检查)。如果我关闭第二个if条件(只查找第一个if条件中匹配的东西),它确实找到了很多匹配项;但是,如果我关闭第一个条件(只查找匹配第二个条件的东西),它就找不到任何东西。 我可能还应该提到两个文件包含大约800.000行,因此为每一行循环遍历一个文件可能不是一个好选择;但是,我想不出更好的一个!我认为使用哈希可能会更容易,但我想不出一种将其编译成哈希的聪明方法。如果你们有任何关于我如何能够完成这项工作的建议,我会很高兴的!

提前多多感谢!

2 个答案:

答案 0 :(得分:1)

这适用于您提供的示例数据。以script.pl alleles.txt hmp.txt运行:

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

open my $AL,  '<', shift or die $!;
open my $HMP, '<', shift or die $!;

# Skip headers
<$AL>;
<$HMP>;

my ($chr_h, $pos_h) = (-1, -1);
while (<$AL>) {
    my ($chr_a, $pos_a) = (split /\t/)[0, 2];
    while ($chr_h < $chr_a and $pos_h < $pos_a) {
        ($chr_h, $pos_h) = (split /\t/, <$HMP>)[2, 3];
    }
    if ($chr_h == $chr_a and $pos_h == $pos_a) {
        print;
       ($chr_h, $pos_h) = (-1, -1);
    }
}

答案 1 :(得分:0)

看起来我必须回答这个问题,因为我无法将代码放入评论中=)

好吧,我刚创建了这个迷你数据集,在其中我通过less搜索了两个文件中相互匹配的两行:

alleles.txt:

rs#     alleles chrom   pos     strand  assembly#       center  protLSID        assayLSID       panelLSID       QCcode  M.10    M.101   M.103
NA      NA      1       10971981        NA      NA      NA      NA      NA      NA      NA      2       1       2
NA      NA      1       11716572        NA      NA      NA      NA      NA      NA      NA      1       1       1

hmp.txt:

chr     pse.bp  bp      nalleles        maf     bur-0   can-0   col-0   ct-1    edi-0   hi-0    kn-0    ler-0   mt-0    no-0    oy-0    po-0    rsch-4  sf-2    ts
1       11230382        10971981        3       14      GGTA    GGTA    GG      GG      GG      GG      GG      GG      GG      GG      GG      GGTA    GG      0
1       12050466        11716572        2       15      A       A       A       A       A       T       A       A       T       A       A       A       T       T

两条线在必填字段中相互匹配,对吗?但是,如果我运行你给我的脚本,它只返回:

1       11230382        10971981        3       14      GGTA    GGTA    GG      GG      GG      GG      GG      GG      GG      GG      GG      GGTA    GG      0

这只是第一行。 为了确保这不是原因,我应该提一下,hmp.txt包含的结尾比M.10,M.101,M.103更多。我只包括前三个,因为实际文件包含大约1000个这些列。 顺便问一下,还有一种方法可以返回标题行吗?我知道我可以手动编写它,因为它不是那么多的文本,但只是为了它... ...

再次感谢您的帮助!

相关问题