如何在数据文件中查找文本并使用perl计算平均值

时间:2014-03-10 12:22:14

标签: perl if-statement awk grep

我想替换一个grep | awk |带有纯perl解决方案的perl命令使其更快更简单地运行。

我希望将input.txt中的每一行与data.txt文件相匹配,并使用匹配的ID名称和数字计算值的平均值。

input.txt包含1列ID号:

FBgn0260798
FBgn0040007
FBgn0046692

我想将每个ID号与相应的ID名称和相关值进行匹配。以下是data.txt的示例,其中第1列是ID号,第2列和第3列是ID name1和ID name2,第3列包含我想要计算平均值的值。

FBgn0260798 CG17665 CG17665 21.4497
FBgn0040007 Gprk1   CG40129 22.4236
FBgn0046692 RpL38   CG18001 1182.88

到目前为止,我使用grep和awk生成一个输出文件,其中包含匹配的ID号和值的相应值,然后使用该输出文件使用以下命令计算计数和平均值:

# First part using grep | awk
exec < input.txt
while read line
    do
            grep -w $line data.txt | cut -f1,2,3,4 | awk '{print $1,$2,$3,$4} ' >> output.txt
    done
 # Second part with perl

open my $input, '<', "output_1.txt" or die; ## the output file is from the first part and has the same layout as the data.txt file

my $total = 0;
my $count = 0;

while (<$input>) {

    my ($name, $id1, $id2, $value) = split;
    $total += $value;
    $count += 1;

}

print "The total is $total\n";
print "The count is $count\n";
print "The average is ", $total / $count, "\n";

这两个部分都可以正常工作,但我想通过运行一个脚本来简化它。我一直试图找到一种更快速的方式在perl中运行整个批次但是经过几个小时的阅读后,我完全不知道如何去做。我一直在玩哈希,数组,if和elsif语句而没有成功。如果有人有建议等,那就太好了。

谢谢, 哈丽特

1 个答案:

答案 0 :(得分:1)

如果我了解您,您的数据文件包含每行的名称以及该行的。其他两个ID并不重要。

您将使用名为输入文件的新文件,该文件将包含数据文件中的匹配名称。这些是您想要平均的值。

最快的方法是创建一个由名称键入的哈希值,这些值将是名称中的 数据文件。因为这是一个哈希,所以您可以快速找到相应的值。这比一遍又一遍地使用相同的数组要快得多。

第一部分将读入data.txt文件,并将名称存储在由名称键入的哈希值中

use strict;
use warnings;
use autodie;   # This way, you don't have to check if you can't open the file
use feature qw(say);

use constant {
    INPUT_NAME  => "input.txt",
    DATA_FILE   => "data.txt",
};

#
# Read in data.txt and get the values and keys
#
open my $data_fh, "<", DATA_FILE;
my %ids;
while ( my $line = <$data_fh> ) {
    chomp $line;
    my ($name, $id1, $id2, $value) = split /\s+/, $line;
    $ids{$name} = $value;
}
close $data_fh;

现在,您已经拥有此哈希,可以轻松阅读input.txt文件并在data.txt文件中找到匹配的名称

open $input_fh, "<", INPUT_FILE;
my $count = 0;
my $total = 0;
while ( my $name = <$input_fh> ) {
    chomp $name;
    if ( not defined $ids{$name} ) {
         die qq(Cannot find matching id "$name" in data file\n);
    }
    $total += $ids{$name};
    $count += 1;
}
close $input_fh;
say "Average = " $total / $count;

您仔细阅读每个文件一次。我假设每个文件中只有一个 name 的实例。