如何从制表符分隔的数据文件中平均列值,忽略标题行和左列?

Posted

技术标签:

【中文标题】如何从制表符分隔的数据文件中平均列值,忽略标题行和左列?【英文标题】:How do I average column values from a tab-separated data file, ignoring a header row and the left column? 【发布时间】:2012-03-29 11:17:06 【问题描述】:

我的任务是从以下名为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

我必须编写一个脚本来打开和读取这个文件,通过将内容拆分成一个数组来读取每一行,然后计算数值的平均值(genomegagpol、@987654326 @),并将上述各列的平均值写入一个新文件。

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

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.

我了解这涉及@$,但即使知道我无法更改错误。

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

#!/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 $average = ();

while (<INFILE>) 
    chomp;
    my @columns = split /\t/;
    $count++;
    if ( $count == 1 ) 
        $average = @columns;
    
    else 
        for( my $i = 1; $i < scalar $average; $i++ )  
            $average[$i] += $columns[$i];
        
    


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

如果有任何见解,我将不胜感激,也非常感谢通过列出您在每个步骤中所做的事情来让我知道 - 如果合适的话。我想学习,如果我能够阅读某人的流程,这对我来说会更有意义。

【问题讨论】:

好的,我看到你已经牢记use warningsuse strict 的诫命。这就是您的错误的来源。您将“平均”声明为数组引用(有点),然后将其用作数组。尝试其中一个或另一个(但不是两者): 1. 将行更改为 @average 或 2. 使用 $average-&gt;[i] 正确取消引用注意,这不会解决整个问题,但它会消除错误消息为您服务,让您专注于逻辑。 哦,我只需要取消引用它。这确实消除了最后两个错误,你是对的,它并没有解决整个问题,因为我现在想出了这个:Can't use string ("5") as an ARRAY ref while "strict refs"在第 23 行, 第 2 行使用。我不确定这里发生了什么...... @PkC 您可能希望更新代码示例以显示代码的最新状态。这对调试更有帮助。 @PkC 并根据输入提供示例输出。欢迎来到 SO。 @Oalders - 感谢您的建议。不幸的是,出于某种原因,我的命令提示符不想在家里运行 perl,尽管出于某种原因它在大学工作。我不知道为什么,但它不断出现:'perl' 不被识别为内部或外部命令、可运行程序或批处理文件。即使我加载了 .bat 文件(与在大学工作的文件相同),也会出现这种情况。我也重启了电脑,还是不行。我还尝试不使用 'perl' 后跟我的 .pl 文件,结果只是出现了一个对话框,上面写着“选择要打开的程序...” 【参考方案1】:

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

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

然后改变if语句里面的逻辑

if ( $count == 1 ) 
    @header = @columns;

现在不要使用@average 作为限制,使用$i &lt; scalar @columns 作为else 语句。 最初 @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";

还有其他方法可以编写此代码,但我认为最好只是更正您的代码,这样您就可以轻松理解您的代码有什么问题。希望对你有帮助

【讨论】:

我只是想非常感谢你。我真的。它工作得很好,我可以看到正确的平均值。 0 为第一列,其他的被视为'header'。 我现在创建了一个“outfile”操作,以便可以将结果打印到文本文件中。 .txt 文件已生成,但其中没有文本。首先,我从修改后的脚本中得到的输出带有以下语句:'code' Argument "" is not numeric in ddition (+) at line X, line Y.'code' 以上出现 5 次,我认为这是由于我的源文件中的非数字标题(如我上面的评论中所述)。然后是“0”(我认为是第一列),然后是 4 个所需的平均值。出于某种原因,我似乎无法打印到文件中。 如果您为此创建另一个问题会更好。 当然,我刚刚发布了一个。我还将发布一些关于我也想了解的另一项任务的内容,但我必须等待发布那个! :)

以上是关于如何从制表符分隔的数据文件中平均列值,忽略标题行和左列?的主要内容,如果未能解决你的问题,请参考以下文章

从制表符分隔的 xls 文件中读取数据

如何从两个制表符分隔的文件中获取枢轴线?

制表符分隔文件的 OleDb 连接字符串

在 VBA Excel 中难以找到行尾

如何从文本文件中用逗号分隔行中的特定行和值

数据文件的内容中,字段中间用制表符Tab键分隔。