我对Perl相对较新,只使用它将小文件转换成不同的格式并在程序之间提供数据。
现在,我需要加强一点。我有一个长度为5,905行的DNA数据文件,每行有32个字段。这些字段没有任何分隔,并且在行内的长度不同,但每个字段在所有5905行上的大小相同。
我需要将每一行输入到文件中的单独数组中,并将该行中的每个字段存储为其自己的变量。我在存储一行时没有任何问题,但是我在连续存储整个文件时遇到了困难。
这就是我将完整数组的第一行分成单个变量的方法:
my $SampleID = substr("@HorseArray", 0, 7);
my $PopulationID = substr("@HorseArray", 9, 4);
my $Allele1A = substr("@HorseArray", 14, 3);
my $Allele1B = substr("@HorseArray", 17, 3);
my $Allele2A = substr("@HorseArray", 21, 3);
my $Allele2B = substr("@HorseArray", 24, 3);
...等
我的问题是:1)我需要将每个5905行存储为单独的数组。 2)我需要能够根据样本ID引用每一行,或者根据种群ID引用一组行并对它们进行排序。
一旦在变量中定义了数据,我就可以对数据进行排序和操作。我只是在构造一个包含这些字段的多维数组时遇到了麻烦,所以我可以随意引用每一行。任何帮助或方向都非常感谢。我已经在这里倾听了Q& A部分,但还没有找到我的问题的答案。
答案 0 :(得分:3)
不将每一行存储在自己的数组中。您需要构建一个数据结构。首先阅读以下教程形式perldoc:
这是一些入门代码:
use strict;
use warnings;
# Array of data samples. We could use a hash as well; which is better
# depends on how you want to use the data.
my @sample;
while (my $line = <DATA>) {
chomp $line;
# Parse the input line
my ($sample_id, $population_id, $rest) = split(/\s+/, $line, 3);
# extract A/B allele pairs
my @pairs;
while ($rest =~ /(\d{1,3})(\d{3})|(\d{1,3}) (\d{1,2})/g) {
push @pairs, {
A => defined $1 ? $1 : $3,
B => defined $2 ? $2 : $4,
};
}
# Add this sample to the list of samples. Store it as a hashref so
# we can access attributes by name
push @sample, {
sample => $sample_id,
population => $population_id,
alleles => \@pairs,
};
}
# Print out all the values of alleles 2A and 2B for the samples in
# population py18. Note that array indexing starts at 0, so allele 2
# is at index 1.
foreach my $sample (grep { $_->{population} eq 'py18' } @sample) {
printf("%s: %d / %d\n",
$sample->{sample},
$sample->{alleles}[1]{A},
$sample->{alleles}[1]{B},
);
}
__DATA__
00292-97 py17 97101 129129 152164 177177 100100 134136 163165 240246 105109 124124 166166 292292 000000 000000 000000
00293-97 py18 89 97 129139 148154 179179 84 90 132134 167169 222222 105105 126128 164170 284292 000000 000000 000000
00294-97 py17 91 97 129133 152154 177183 100100 134140 161163 240240 103105 120128 164166 290292 000000 000000 000000
00295-97 py18 97 97 131133 148162 177179 84100 132134 161167 240252 111111 124128 164166 284290 000000 000000 000000
答案 1 :(得分:2)
我首先循环遍历这些行并将每个字段解析为字段的哈希值,然后我会为每个索引构建一个哈希值。
my %by_sample_id; # this will be a hash of hashes
my %by_population_id; # a hash of lists of hashes
foreach (<FILEHANDLE>) {
chomp; # remove newline
my %h; # new hash
$h{SampleID} = substr($_, 0, 7);
$h{PopulationID} = substr($_, 9, 4);
# etc...
$by_sample_id{ $h{SampleID} } = \%h; # a reference to %h
push @{$by_population_id{ $h{PopulationID} }}, \%h; # pushes hashref onto list
}
然后,您可以使用任一索引来访问您感兴趣的数据:
say "Allele1A for sample 123123: ", $by_sample_id{123123}->{Allele1A};
say "all the Allele1A values for population 432432: ",
join(", ", map {$_->{Allele1A}} @{$by_population_id{432432}});
答案 2 :(得分:1)
我将假设这不是一次性的计划,所以我的方法会略有不同。 我做了大量的数据混合,过了一段时间,我厌倦了编写针对数据结构的查询。
所以 -
我会将数据提供给SQLite数据库(或其他sql DB),然后使用Perl DBI编写Perl查询。这使得复杂性远远超过了一个简单的“解析和破解”,但是在您编写了几个脚本对同一数据进行查询之后,很明显这是一个痛苦,必须有一个更好的方式
您将拥有与此类似的架构
create table brians_awesome_data (id integer, population_id varchar(32), chunk1 integer, chunk2 integer...);
然后,在你使用了一些mobrule和Michael的优秀解析之后,你就会循环并执行一些INSERT IN到你的awesome_data表。
然后,您可以为您的SQL程序使用CLI并执行“select ... where ...”查询以快速获取所需的数据。
或者,如果它更具分析性/管道性,您可以使用DBI Perl编写脚本并将数据导入分析例程。
相信我,这是比一遍又一遍地对数据结构编写查询更好的方法。