如何对选项卡分隔的数据文件中的列值进行平均,忽略标题行和左列?

时间:2012-03-13 02:19:10

标签: perl strict

我的任务是从以下数据文件计算平均值,标题为Lab1_table.txt

retrovirus      genome  gag     pol     env
HIV-1           9181    1503    3006    2571
FIV             9474    1353    2993    2571
KoRV            8431    1566    3384    1980
GaLV            8088    1563    3498    2058
PERV            8072    1560    3621    1532

我必须编写一个打开并阅读此文件的脚本,通过将内容拆分为数组来读取每一行,并计算出数值的平均值(genomegag,{{ 1}},pol),并将每个上述列的平均值写入新文件。

我一直在努力弄清楚如何不考虑第一行或第一列,但每次我尝试在命令行上执行时,我都会遇到“显式包名”错误

env

我知道这涉及Global symbol @average requires explicit package name at line 23. Global symbol @average requires explicit package name at line 29. Execution aborted due to compilation errors. @,但即使知道我无法更改错误。

这是我的代码,但我强调我上周开始这是一个初学者:

$

我很感激任何见解,我也非常感谢通过列表编号告诉我你在每一步所做的事情 - 如果合适的话。我想学习,如果我能够阅读某人的过程,那对我来说会更有意义。

1 个答案:

答案 0 :(得分:2)

以下是您需要更改的要点 使用另一个变量作为标题

my $count = 0;
my @header = ();
my @average = ();

然后改变if语句

中的逻辑
if ( $count == 1 ) {
    @header = @columns;
}

现在不要使用@average作为限制,对else语句使用$i < scalar @columns。 最初@average为零,你永远不会进入for循环。

else {
    for( my $i = 1; $i < scalar @columns; $i++ )  {
        $average[$i] += $columns[$i];
    }
}

最后将-1添加到您的计数器。请记住,在解析标题时递增计数器

for( my $i = 1; $i < scalar @average; $i++ ) {
    print $average[$i]/($count-1), "\n";
}

这是最终的代码
您可以利用@header整齐地显示结果

#!/usr/bin/perl -w

use strict;

my $infile = "Lab1_table.txt"; # This is the file path
open INFILE, $infile or die "Can't open $infile: $!"; 

my $count = 0;
my @header = ();
my @average = ();

while (<INFILE>) {
    chomp;


    my @columns = split /\t/;
    $count++;
    if ( $count == 1 ) {
        @header = @columns;
    }
    else {
        for( my $i = 1; $i < scalar @columns; $i++ )  {
            $average[$i] += $columns[$i];
        }
    }
} 

for( my $i = 1; $i < scalar @average; $i++ ) {
    print $average[$i]/($count-1), "\n";
}

还有其他方法可以编写此代码,但我认为最好只更正代码,以便您可以轻松了解代码的错误。希望它有所帮助