我在编写脚本时遇到一些麻烦,该脚本遍历两个不同的表并根据身份过滤行。我只是意识到这可能超出了我对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行,因此为每一行循环遍历一个文件可能不是一个好选择;但是,我想不出更好的一个!我认为使用哈希可能会更容易,但我想不出一种将其编译成哈希的聪明方法。如果你们有任何关于我如何能够完成这项工作的建议,我会很高兴的!
提前多多感谢!
虾
答案 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个这些列。 顺便问一下,还有一种方法可以返回标题行吗?我知道我可以手动编写它,因为它不是那么多的文本,但只是为了它... ...
再次感谢您的帮助!
虾