Как усреднить значения столбцов из файла данных, разделенных табуляцией, игнорируя строку заголовка и левый столбец? - PullRequest
3 голосов
/ 13 марта 2012

Моя задача - вычислить средние значения из следующего файла данных с именем 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

Мне нужно написать скрипт, который откроет и прочитает этот файл, прочитает каждую строку, разбивая содержимое на массив и вычисляя среднее значение чисел (genome, gag, pol, * 1008). *) и запишите в новый файл среднее значение для каждого из вышеупомянутых столбцов.

Я изо всех сил пытался выяснить, как не учитывать первую строку или первый столбец, но каждый раз, когда я пытаюсь выполнить в командной строке, я продолжаю выдавать ошибки «явного имени пакета» .

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";
}

Буду признателен за любую проницательность, и я также буду признателен, если сообщите мне, перечислив нумерацию, что вы делаете на каждом этапе - если это уместно. Я хотел бы учиться, и для меня было бы больше смысла, если бы я мог прочитать, что это был за процесс.

1 Ответ

2 голосов
/ 13 марта 2012

Вот точки, которые необходимо изменить
Используйте другую переменную для заголовков

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

, затем измените логику внутри оператора if

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

Теперь не используйте @average для ограничения, используйте $i < 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";
}

ТамЕсть и другие способы написания этого кода, но я подумал, что было бы лучше просто исправить ваш код, чтобы вы могли легко понять, что не так с вашим кодом.Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...