如何使用另一个文件的值优化一个文件中的搜索?
How can I optimize searching in one file by using values from another one?
我有两种文件,假设文件 A 和文件 B。
文件 A 有这样的行
scaffold10920 13740 14020 chr19.3.4051.27470346.27470626 280 100.00
文件B有这样的行
283 2 0 0 0 0 0 0 + chr16.1.1.10933.11218 285 0 285 scaffold476 838469 193881 194166 1 285, 0, 193881,
前面的示例是每个文件中的一行。这两个文件中的所有字段均以制表符分隔。
我想过滤文件 B,只保留与文件 A 中的第一个和第四个字段具有相同值的行(例如 scaffold10920
和 chr19.3.4051.27470346.27470626
)。为此,我为文件 A 创建了一个散列 table,如下所示
{chr19.3.4051.27470346.27470626} --> scaffold10920
我正在文件 B 中搜索它。
这是我的脚本:
#!/app/languages/perl/5.14.2/bin/perl
use strict;
use warnings;
use Data::Dumper;
my $chromosome = $ARGV[0];
my @mykeys = `cat rightChromosome/$chromosome.scaffolds.txt| sort -u`;
my %hces_hash;
foreach my $key_line (@mykeys) {
#$key_line = $_;
chomp($key_line);
my @token = split('\t', $key_line);
my $hce = $token[3];
my $scaff = $token[0];
$hces_hash{$hce} = $scaff;
}
#print Dumper(\%hces_hash);
foreach my $key (keys %hces_hash) {
chomp($key);
my $scaffold = $hces_hash{$key};
my $command = "cat psl_best/$chromosome.best.psl|grep -w $key";
my @belongs = `$command`;
chomp(@belongs);
my $count = scalar(@belongs);
foreach my $element (@belongs) {
my @element_token = split('\t', $element);
my $scaff_psl = $element_token[13];
my $hce_name = $element_token[9];
if ($scaffold eq $scaff_psl) {
#print "$element\n";
open FILE, ">>psl_raw/$chromosome.best.raw.psl" or die $!;
print FILE "$element\n";
}
}
我的脚本可以运行,但是速度很慢。有什么办法可以优化吗?
这会工作得更快,因为它只读取每个文件一次。由于没有数据,我无法对其进行测试,但我已经检查过它是否可以编译。您可能想更改某些变量的名称,但我已经做出了最好的猜测。
它的工作原理是使用 字段 1 和 scaffolds 文件的字段 4 的键构建散列,它们之间有一个制表符.散列值无关紧要——只是一个正数。然后它读取 best 文件并从字段 14 和 10 构建相同的密钥,并在将记录打印到输出文件之前简单地检查它是否出现在散列中。
你不应该 shell 脱离 Perl 来做一些简单的事情,比如读取文件。只有当你需要做一些超出 Perl 能力的事情时才有必要。我在 sort
调用中没有看到任何一点,因为它只是花时间对数据进行排序,这些数据一旦存储在哈希中就会再次变得无序。
#!/app/languages/perl/5.14.2/bin/perl
use strict;
use warnings;
use 5.010;
use autodie;
our @ARGV = qw/ chr2 /;
chdir 'psl_files';
my $raw_dir = 'psl_raw';
if ( -e $raw_dir ) {
die qq{Can't make "$raw_dir"\n} unless -d $raw_dir;
# ' fix highlighting
}
else {
mkdir $raw_dir;
}
my ($chromosome) = @ARGV or die "Usage: [=10=] <chromosome>\n";
my $scaff_file = "rightChromosome/$chromosome.scaffolds.txt";
my $best_file = "psl_best/$chromosome.best.psl";
my $raw_file = "psl_raw/$chromosome.best.raw.psl";
# For provided data
$scaff_file = "chr2.scaffolds.txt";
$best_file = "chr2.best_noHeaded.psl";
open my $scaff_fh, '<', $scaff_file;
my %hces_hash;
while ( <$scaff_fh> ) {
chomp;
my @fields = split /\t/;
my $key = join "\t", @fields[0,3];
++$hces_hash{$key};
}
close $scaff_fh;
open my $best_fh, '<', $best_file;
open my $raw_fh, '>', $raw_file;
while ( <$best_fh> ) {
chomp;
my @fields = split /\t/;
my $key = join "\t", @fields[13,9];
print $raw_fh "$_\n" if $hces_hash{$key};
}
close $raw_fh;
close $best_fh;
我有两种文件,假设文件 A 和文件 B。 文件 A 有这样的行
scaffold10920 13740 14020 chr19.3.4051.27470346.27470626 280 100.00
文件B有这样的行
283 2 0 0 0 0 0 0 + chr16.1.1.10933.11218 285 0 285 scaffold476 838469 193881 194166 1 285, 0, 193881,
前面的示例是每个文件中的一行。这两个文件中的所有字段均以制表符分隔。
我想过滤文件 B,只保留与文件 A 中的第一个和第四个字段具有相同值的行(例如 scaffold10920
和 chr19.3.4051.27470346.27470626
)。为此,我为文件 A 创建了一个散列 table,如下所示
{chr19.3.4051.27470346.27470626} --> scaffold10920
我正在文件 B 中搜索它。
这是我的脚本:
#!/app/languages/perl/5.14.2/bin/perl
use strict;
use warnings;
use Data::Dumper;
my $chromosome = $ARGV[0];
my @mykeys = `cat rightChromosome/$chromosome.scaffolds.txt| sort -u`;
my %hces_hash;
foreach my $key_line (@mykeys) {
#$key_line = $_;
chomp($key_line);
my @token = split('\t', $key_line);
my $hce = $token[3];
my $scaff = $token[0];
$hces_hash{$hce} = $scaff;
}
#print Dumper(\%hces_hash);
foreach my $key (keys %hces_hash) {
chomp($key);
my $scaffold = $hces_hash{$key};
my $command = "cat psl_best/$chromosome.best.psl|grep -w $key";
my @belongs = `$command`;
chomp(@belongs);
my $count = scalar(@belongs);
foreach my $element (@belongs) {
my @element_token = split('\t', $element);
my $scaff_psl = $element_token[13];
my $hce_name = $element_token[9];
if ($scaffold eq $scaff_psl) {
#print "$element\n";
open FILE, ">>psl_raw/$chromosome.best.raw.psl" or die $!;
print FILE "$element\n";
}
}
我的脚本可以运行,但是速度很慢。有什么办法可以优化吗?
这会工作得更快,因为它只读取每个文件一次。由于没有数据,我无法对其进行测试,但我已经检查过它是否可以编译。您可能想更改某些变量的名称,但我已经做出了最好的猜测。
它的工作原理是使用 字段 1 和 scaffolds 文件的字段 4 的键构建散列,它们之间有一个制表符.散列值无关紧要——只是一个正数。然后它读取 best 文件并从字段 14 和 10 构建相同的密钥,并在将记录打印到输出文件之前简单地检查它是否出现在散列中。
你不应该 shell 脱离 Perl 来做一些简单的事情,比如读取文件。只有当你需要做一些超出 Perl 能力的事情时才有必要。我在 sort
调用中没有看到任何一点,因为它只是花时间对数据进行排序,这些数据一旦存储在哈希中就会再次变得无序。
#!/app/languages/perl/5.14.2/bin/perl
use strict;
use warnings;
use 5.010;
use autodie;
our @ARGV = qw/ chr2 /;
chdir 'psl_files';
my $raw_dir = 'psl_raw';
if ( -e $raw_dir ) {
die qq{Can't make "$raw_dir"\n} unless -d $raw_dir;
# ' fix highlighting
}
else {
mkdir $raw_dir;
}
my ($chromosome) = @ARGV or die "Usage: [=10=] <chromosome>\n";
my $scaff_file = "rightChromosome/$chromosome.scaffolds.txt";
my $best_file = "psl_best/$chromosome.best.psl";
my $raw_file = "psl_raw/$chromosome.best.raw.psl";
# For provided data
$scaff_file = "chr2.scaffolds.txt";
$best_file = "chr2.best_noHeaded.psl";
open my $scaff_fh, '<', $scaff_file;
my %hces_hash;
while ( <$scaff_fh> ) {
chomp;
my @fields = split /\t/;
my $key = join "\t", @fields[0,3];
++$hces_hash{$key};
}
close $scaff_fh;
open my $best_fh, '<', $best_file;
open my $raw_fh, '>', $raw_file;
while ( <$best_fh> ) {
chomp;
my @fields = split /\t/;
my $key = join "\t", @fields[13,9];
print $raw_fh "$_\n" if $hces_hash{$key};
}
close $raw_fh;
close $best_fh;