Perl -> 在数组散列的散列中比较数组中的相同位置
Perl -> compare same postitions in arrays in a hash of hashes of arrays
我正在处理同事制作的 bash 脚本。由于 bash 中没有多维数据结构,因此有很多解决方法来处理输入文件。当我看到他的脚本时,我认为 Perl 可以更轻松地处理它。我认为我在转换方面做得不错,但现在我被卡住了。对于那些知道的人,输入文件采用变体调用格式 (VCF)。基本上是一个制表符分隔的文本文件,在特定列中包含特定信息位。输入文件如下所示:
##fileformat=VCFv4.2
#CHROM POS ID REF ALT QUAL FILTER INFO FORMAT MBWGS139
AF2122_NC002945 1012102 . A G 1137.77 . AC=2;AF=1.00;AN=2 GT:AD:DP:GQ:PL 1/1:0,29:29:87:1166,87,0
AF2122_NC002945 103811 . C G 241.84 . AC=2;AF=1.00;AN=2 GT:AD:DP:GQ:PL 1/1:0,6:6:18:270,18,0
我做的第一件事是将所有文件信息存储在散列中。通过逐行循环每个文件,多个文件(或示例)都集成在 "master" 哈希中。主哈希的构造如下:
push(@{ $vcfs{$sample}{$CHROM}{$POS} }, $ID, $REF, $ALT, $QUAL, $FILTER, $INFO, $FORMAT, $SAMPLE);
然后我需要过滤掉"bad"个职位。我将在此处跳过该代码,但我保留的信息位存储在一个新的散列中,该散列是这样创建的:
push ( @{ $fastas{$sample}{$chrom}{$pos} }, $allele);
假设 $allele = $ALT(但它有点复杂)。所以在 %fasta 里面它看起来像这样:
Sample1
chrom1
pos1 = A
pos2 = T
chrom2
pos1 = A
pos2 = G
Sample2
chrom1
pos1 = C
pos2 = T
chrom2
pos1 = A
pos2 = G
看到这个就像我使用 Data::Dumper 打印它一样...您还可以看到,对于那部分代码,我放弃了很多信息。
最后一个过滤步骤是去除特定位置所有样本共有的"alleles"。在前面的例子中,只有 pos1 的 chrom 会被保留。最终的哈希值如下所示:
Sample1
chrom1
pos1 = A
Sample2
chrom1
pos1 = C
我找到了一种方法,就是放弃位置信息。我需要保留它。如果有人能在这里帮助我,我将不胜感激。如果有帮助,我可以提供我当前的解决方案。
谢谢,
马可
我找到了 2 种方法来获得所需的输出。但是,鉴于只有 4 个等位基因需要考虑,我想知道在更大的数据集中怎么可能有一个是独一无二的。
该解决方案包含一个 %count
散列,可用于查找独特的等位基因。
#!/usr/bin/perl
use strict;
use warnings;
my (%fastas, %counts);
my ($sample, $chr);
while (<DATA>) {
if (/^(\S.+)$/) {
$sample = ;
}
elsif (/^\t(\S.+)$/) {
$chr = ;
}
elsif (/^\t\t(pos\d+)\s=\s([TAGC])$/) {
my $pos = ,
my $allele = ;
push @{ $fastas{$sample}{$chr}{$pos} }, $allele;
$counts{$allele}++;
}
else {
die "Unknown input line $.: <<$_>>";
}
}
for my $sample (keys %fastas) {
my $chr_ref = $fastas{$sample};
for my $chr (keys %$chr_ref) {
my $pos_ref = $chr_ref->{$chr};
for my $pos (keys %$pos_ref) {
my $allele_ref = $pos_ref->{$pos};
for my $allele (@$allele_ref) {
print "$sample $chr $pos $allele\n"
if $counts{$allele} == 1;
}
}
}
}
__DATA__
Sample1
chrom1
pos1 = A
pos2 = T
chrom2
pos1 = A
pos2 = G
Sample2
chrom1
pos1 = C
pos2 = T
chrom2
pos1 = A
pos2 = G
第二种解决方案利用了Deep::Hash::Utils模块。它通过消除第一个解决方案中的嵌套循环来简化代码。
#!/usr/bin/perl
use strict;
use warnings;
use Deep::Hash::Utils 'reach';
my (%fastas, %counts);
my ($sample, $chr);
while (<DATA>) {
if (/^(\S.+)$/) {
$sample = ;
}
elsif (/^\t(\S.+)$/) {
$chr = ;
}
elsif (/^\t\t(pos\d+)\s=\s([TAGC])$/) {
my $pos = ,
my $allele = ;
push @{ $fastas{$sample}{$chr}{$pos} }, $allele;
$counts{$allele}++;
}
else {
die "Unknown input line $.: <<$_>>";
}
}
while (my @list = reach(\%fastas)) {
my $allele = $list[-1];
print "@list\n" if $counts{$allele} == 1;
}
__DATA__
Sample1
chrom1
pos1 = A
pos2 = T
chrom2
pos1 = A
pos2 = G
Sample2
chrom1
pos1 = C
pos2 = T
chrom2
pos1 = A
pos2 = G
在您提供的数据集上,两种解决方案都打印了 Sample2 chrom1 pos1 C
。
我正在处理同事制作的 bash 脚本。由于 bash 中没有多维数据结构,因此有很多解决方法来处理输入文件。当我看到他的脚本时,我认为 Perl 可以更轻松地处理它。我认为我在转换方面做得不错,但现在我被卡住了。对于那些知道的人,输入文件采用变体调用格式 (VCF)。基本上是一个制表符分隔的文本文件,在特定列中包含特定信息位。输入文件如下所示:
##fileformat=VCFv4.2
#CHROM POS ID REF ALT QUAL FILTER INFO FORMAT MBWGS139
AF2122_NC002945 1012102 . A G 1137.77 . AC=2;AF=1.00;AN=2 GT:AD:DP:GQ:PL 1/1:0,29:29:87:1166,87,0
AF2122_NC002945 103811 . C G 241.84 . AC=2;AF=1.00;AN=2 GT:AD:DP:GQ:PL 1/1:0,6:6:18:270,18,0
我做的第一件事是将所有文件信息存储在散列中。通过逐行循环每个文件,多个文件(或示例)都集成在 "master" 哈希中。主哈希的构造如下:
push(@{ $vcfs{$sample}{$CHROM}{$POS} }, $ID, $REF, $ALT, $QUAL, $FILTER, $INFO, $FORMAT, $SAMPLE);
然后我需要过滤掉"bad"个职位。我将在此处跳过该代码,但我保留的信息位存储在一个新的散列中,该散列是这样创建的:
push ( @{ $fastas{$sample}{$chrom}{$pos} }, $allele);
假设 $allele = $ALT(但它有点复杂)。所以在 %fasta 里面它看起来像这样:
Sample1
chrom1
pos1 = A
pos2 = T
chrom2
pos1 = A
pos2 = G
Sample2
chrom1
pos1 = C
pos2 = T
chrom2
pos1 = A
pos2 = G
看到这个就像我使用 Data::Dumper 打印它一样...您还可以看到,对于那部分代码,我放弃了很多信息。
最后一个过滤步骤是去除特定位置所有样本共有的"alleles"。在前面的例子中,只有 pos1 的 chrom 会被保留。最终的哈希值如下所示:
Sample1
chrom1
pos1 = A
Sample2
chrom1
pos1 = C
我找到了一种方法,就是放弃位置信息。我需要保留它。如果有人能在这里帮助我,我将不胜感激。如果有帮助,我可以提供我当前的解决方案。
谢谢, 马可
我找到了 2 种方法来获得所需的输出。但是,鉴于只有 4 个等位基因需要考虑,我想知道在更大的数据集中怎么可能有一个是独一无二的。
该解决方案包含一个 %count
散列,可用于查找独特的等位基因。
#!/usr/bin/perl
use strict;
use warnings;
my (%fastas, %counts);
my ($sample, $chr);
while (<DATA>) {
if (/^(\S.+)$/) {
$sample = ;
}
elsif (/^\t(\S.+)$/) {
$chr = ;
}
elsif (/^\t\t(pos\d+)\s=\s([TAGC])$/) {
my $pos = ,
my $allele = ;
push @{ $fastas{$sample}{$chr}{$pos} }, $allele;
$counts{$allele}++;
}
else {
die "Unknown input line $.: <<$_>>";
}
}
for my $sample (keys %fastas) {
my $chr_ref = $fastas{$sample};
for my $chr (keys %$chr_ref) {
my $pos_ref = $chr_ref->{$chr};
for my $pos (keys %$pos_ref) {
my $allele_ref = $pos_ref->{$pos};
for my $allele (@$allele_ref) {
print "$sample $chr $pos $allele\n"
if $counts{$allele} == 1;
}
}
}
}
__DATA__
Sample1
chrom1
pos1 = A
pos2 = T
chrom2
pos1 = A
pos2 = G
Sample2
chrom1
pos1 = C
pos2 = T
chrom2
pos1 = A
pos2 = G
第二种解决方案利用了Deep::Hash::Utils模块。它通过消除第一个解决方案中的嵌套循环来简化代码。
#!/usr/bin/perl
use strict;
use warnings;
use Deep::Hash::Utils 'reach';
my (%fastas, %counts);
my ($sample, $chr);
while (<DATA>) {
if (/^(\S.+)$/) {
$sample = ;
}
elsif (/^\t(\S.+)$/) {
$chr = ;
}
elsif (/^\t\t(pos\d+)\s=\s([TAGC])$/) {
my $pos = ,
my $allele = ;
push @{ $fastas{$sample}{$chr}{$pos} }, $allele;
$counts{$allele}++;
}
else {
die "Unknown input line $.: <<$_>>";
}
}
while (my @list = reach(\%fastas)) {
my $allele = $list[-1];
print "@list\n" if $counts{$allele} == 1;
}
__DATA__
Sample1
chrom1
pos1 = A
pos2 = T
chrom2
pos1 = A
pos2 = G
Sample2
chrom1
pos1 = C
pos2 = T
chrom2
pos1 = A
pos2 = G
在您提供的数据集上,两种解决方案都打印了 Sample2 chrom1 pos1 C
。