Как я могу использовать Perl для суммирования отдельных столбцов в текстовом файле? - PullRequest
1 голос
/ 23 июля 2011

У меня большие текстовые файлы в этом формате, и я хотел бы провести статистический анализ этих чисел, начиная с добавления столбцов (игнорируя первую строку).Я пытался посмотреть на другие примеры и изменить их, но у меня плохое программирование!Поэтому мне интересно, если кто-то может указать мне правильное направление, спасибо!

AF3     F7      F3      FC5     T7      P7      O1      O2      P8      T8      FC6 
4464.62 4285.13 4503.59 4505.64 4455.9  4341.03 4257.95 4306.67 4299.49 4180    4461.54 
4473.85 4288.72 4510.26 4508.72 4455.38 4347.18 4265.64 4318.97 4310.26 4184.1  4468.21 
4474.87 4289.74 4516.92 4510.77 4450.26 4345.13 4272.82 4332.82 4312.82 4188.72 4464.62

Ответы [ 6 ]

4 голосов
/ 23 июля 2011

Это базовый скрипт, который дает вам массив с суммированными столбцами. Также держит заголовки. Выходные данные разделены табуляцией. Поскольку я не знаю формат вашего входного файла, я просто разделил пробел.

Использование:

$ script.pl input.txt > output.txt

Код:

use strict;
use warnings;
use ARGV::readonly;

my @data;
my @headers = split ' ', <>;

while (<>) {
    my @row = split;
    $data[$_] += $row[$_] for (0 .. $#row);
}

$" = "\t";
print "@headers", "\n";
print "@data";

Выход:

AF3     F7      F3      FC5     T7      P7      O1      O2      P8      T8
FC6
13413.34        12863.59        13530.77        13525.13        13361.54
13033.34        12796.41        12958.46        12922.57        12552.82
13394.37
1 голос
/ 24 июля 2011

Для манипулирования массивами Perl имеет PDL, что находится в вене MatLab или IDL.

Пример создания и использования PDL:

#!/usr/bin/env perl

use strict;
use warnings;

use PDL;

use Scalar::Util 'looks_like_number';

# get data into proper format
# N.B. fast and dirty method
my $line_number = 0;
my @data;
while(<DATA>) {
  $line_number++;

  #ignore whitespace or empty lines
  next if /^\s*$/;

  my @line = split;

  #ignore lines with non-numeric data
  if ( grep { ! looks_like_number $_ } @line ) {
    print "line $line_number contains non-numeric data, skipping\n";
    next;
  }

  push @data, \@line;
}

#create PDL object (called piddle)
my $pdl = pdl(@data);

print "PDL:\n";
print $pdl;

print "Sum columns:\n";
#sumover acts on 0th dim, so "transpose" 0 and 1
print sumover $pdl->xchg(0,1);


__DATA__
AF3     F7      F3      FC5     T7      P7      O1      O2      P8      T8      FC6 
4464.62 4285.13 4503.59 4505.64 4455.9  4341.03 4257.95 4306.67 4299.49 4180    4461.54 
4473.85 4288.72 4510.26 4508.72 4455.38 4347.18 4265.64 4318.97 4310.26 4184.1  4468.21 
4474.87 4289.74 4516.92 4510.77 4450.26 4345.13 4272.82 4332.82 4312.82 4188.72 4464.62

Конечно, вы, скорее всего, будете загружать данные из файла, поэтому вместо того, чтобы зацикливаться на <DATA>, вы будете зацикливаться на некотором дескрипторе файла.

После того, как вы создадите объект, функция, такая как sumover или функции в PDL::Ufunc, может выполнить работу за вас.

При установке: У меня есть сообщение о установке PDL в Ubuntu, в противном случае посмотрите вики .

0 голосов
/ 26 марта 2013

Однострочный подход:

$ perl -MList::Util=sum -lane 'print sum(@F[1 .. $#F])' < data.txt

0
43596.94
43657.44
43684.62

Объяснение:

  • perl: вызов Perl, дух;
  • -MList::Util=sum: импорт sum() функция из модуля List :: Util , которая является частью установки Perl по умолчанию;
  • -lane: краткий способ задания -l -a -n -e параметров, где:
    • -l: включает автоматическую обработку окончания строки (удаляет символ новой строки при вводе, добавляет при выводе);
    • -a: включает режим автоматического разделения (по умолчанию разбивает каждую строку на словеграница без слов и помещает результаты в массив @F);
    • -n: повторяется на входе;
    • -e: код для оценки.
  • print sum @F[1 .. $#F]: наконец, сам код Perl:
    • print: не требует пояснений;
    • sum: то же самое;
    • @F[1 .. $#F]: фрагмент из массива @F, начиная с элемента # 1 (первый элемент # 0) и до последнего элемента ($#F - индекс до последнего элемента @F).

Наблюдение:первая строка вывода - 0 , потому что Perl оценивает нечисловые значения (заголовки) как числовые 0.

0 голосов
/ 26 марта 2013

perl - неплохой выбор, но для такой простой задачи я бы всегда использовал уже имеющийся набор инструментов (в Unix).

  1. избавиться от заголовка

    sed '2, $! D'

  2. сумма n-го столбца

    awk '{sum + = $ n}; END {печать суммы} '

так что все вместе, делая это для третьего столбца:

sed '2,$!d' <filename> | awk '{sum += $3}; END {print sum}'

если ваша реализация awk выполняет усечение, это может быть лучше:

(awk '{print $3}' <filename> | sed '2,$!d' | tr "\012" "+"; echo "0") | bc 

или это:

(awk '{print $3}' <filename> | sed '2,$!d' | paste -sd+ -) | bc

(для некоторых реализаций пасты требуется указание '-' для чтения из стандартного ввода.

e7 v01L4! 13530,77:)

СПОЙЛЕР

если вы придерживаетесь Perl, как насчет этого:

perl -nle '$sum += $_ } END { print $sum' <filename>
0 голосов
/ 24 апреля 2012

PDL-2.4.7 rcols может использоваться для чтения данных столбца, включая идентификаторы столбцов из первой строки файла.Затем суммы можно рассчитать, как указано выше, используя процедуру PDL sumover:

use strict;
use warnings;

use PDL;

my $hdr = [];
my $pdl = rcols( \*DATA, [], { colids=>$hdr } );

print "PDL:\n";
print $pdl;

print "Column IDs: @{$hdr}\n";

print "Sum columns:\n";
print sumover $pdl;


__DATA__
AF3     F7      F3      FC5     T7      P7      O1      O2      P8      T8      FC6 
4464.62 4285.13 4503.59 4505.64 4455.9  4341.03 4257.95 4306.67 4299.49 4180    4461.54 
4473.85 4288.72 4510.26 4508.72 4455.38 4347.18 4265.64 4318.97 4310.26 4184.1  4468.21 
4474.87 4289.74 4516.92 4510.77 4450.26 4345.13 4272.82 4332.82 4312.82 4188.72 4464.62

См. Веб-страницу PDL для получения дополнительной информации.Список рассылки perldl часто является лучшим способом задать вопросы или пообщаться с разработчиками PDL или сообществом пользователей.Попробуйте help rcols в оболочке pdl2 для документации по всем функциям rcols.

0 голосов
/ 23 июля 2011

Если сумма - это все, что вам нужно, то Ответ TLP достаточно твердый.


Но если план состоит в том, чтобы реализовать больше статистических функций, зачем заново изобретать колесо? CPAN - это репозиторий модулей Perl, собранный сообществом. Скорее всего, кто-то уже написал модуль для выполнения той же функциональности, что и вы.

Это (в идеале) позволяет вам сосредоточиться больше на удовлетворении ваших потребностей, а не на кодировании.

Хотя лично меня не устраивают модули Статистика , доступные в CPAN, похоже, что Statistics::Descriptive точно удовлетворяет насущные потребности этой проблемы.


Давным-давно меня пугала мысль о необходимости установки модуля из CPAN. Вот несколько шагов, с которых можно начать.

Проверьте, установлен ли модуль уже

$ perl -e 'use Statistics::Descriptive;'

Если он установлен, вы не увидите выходных данных. Если нет, Perl будет жаловаться:

Невозможно найти Statistics / Descriptive.pm в @INC ...

BEGIN не удалось - компиляция прервана в строке -e 1.

Установить модуль (если его там уже нет)

$ cpan Statistics::Descriptive

Используйте модуль (при условии, что установка прошла успешно)

use strict;
use warnings;

use Statistics::Descriptive;

Примечание

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

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