2013-04-24 3 views
0

Я построил несколько сценариев для организации вывода данных с тестового оборудования, но я нахожусь с ментальным блокпостом с этим.Таблица сортированных данных здания с использованием hash

Испытательное оборудование контролирует четыре типа ввода (Data1, Data2, Data3, Data4) от нескольких субъектов (с идентификаторами ID1, ID2 и т. Д.) И записывает каждый из интервалов с отметкой даты и времени. CSV-файл, сбрасываемый оборудованием, организован следующим образом:

Start,Date,Time0 
Subject,ID1,ID2,[...],ID# 

Date,Time1 
Data1,aa1,aa2,[...],aa# 
Data2,ba1,ba2,[...],ba# 
Data3,ca1,ca2,[...],ca# 
Data4,da1,da2,[...],da# 

Date,Time2 
Data1,ab1,ab2,[...],ab# 
Data2,bb1,bb2,[...],bb# 
Data3,cb1,cb2,[...],cb# 
Data4,db1,db2,[...],db# 

... и так далее.

«Пуск» идентифицирует эту строку как начало данных; «Объект» идентифицирует строку как строку, содержащую идентификаторы субъекта; «Data1» - «Data4» идентифицируют строку как те, которые содержат данные для этого типа данных в определенный промежуток времени, указанный предыдущей датой и временем.

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

Data1,Subject,ID1,ID2,[...],ID# 
Date,Time1,aa1,aa2,[...],aa# 
Date,Time2,ab1,ab2,[...],ab# 
... 

Data2,Subject,ID1,ID2,[...],ID# 
Date,Time1,ba1,ba2,[...],ba# 
Date,Time2,bb1,bb2,[...],bb# 
... 

Цель состоит в том, чтобы каждый из четырех типов данных в отдельных блоках, так что временные данные для любого данного субъекта (ID1 - ID #) будут находиться в одном столбце с указанием даты и времени в качестве начальных столбцов. («DataX» и «Subject» в приведенном выше примере просто используются в качестве заголовков столбцов.)

В настоящее время я делаю это, помещая каждую строку в отдельный массив. Это был быстрый и грязный способ добиться успеха; сценарий захватывает время и дату и выталкивает строку идентификатора в каждый из четырех массивов (по одному для каждого типа данных), а затем продолжает последовательно добавлять каждую строку данных на основе типа данных. Вывод просто печатает каждый массив по строкам, добавляет пустую строку, а затем печатает следующий массив. Это работает, но в идеале я хотел бы сортировать столбцы данных по идентификатору объекта, а затем распечатывать данные, не теряя вертикальную сортировку по дате и метке времени. (Поскольку данные уже отсортированы по вертикали, в настоящее время у меня нет сортировки на массивах перед печатью.)

Каков самый простой способ сделать это? Мысленно пытаюсь разобрать, как связать данные в строке Y, колонке X с идентификатором объекта в столбце X в файле CSV. Каждый другой файл вывода данных, который я использовал, либо сохраняет идентификатор объекта как первый элемент в каждой строке, либо имеет один файл для каждого объекта, что упрощает его.

Примечание: поскольку время/дата в отдельной строке, я использую переменную для каждого; если скрипт обнаруживает строку, содержащую новое время и/или дату, она обновляет значение переменной.

Редактировать - Я включил некоторые предложения Бородина (оставляя обработку FH по строке, а не по абзацу). У меня есть данные из строки темы втягиваются в массив (@ids), и я толкая строки данных в хэш с использованием даты/времени и ID в качестве ключей:

my ($datatype, @fields) = @line; 
push @keys, $datatype unless exists $data{$datatype}; 
my $datetime = "$date\,$time"; 
push @timestamps, $datetime unless exists $data{$datetime}; 
for my $i (0 .. $#fields) { 
    push @{$data{$datetime}{$ids[$i]}}=>$fields[$i] 
    }; 

Я также сбросив пары даты и время в второй массив для поддержания порядка (@timestamps). Проблема на этом этапе заключается в том, что у меня возникают проблемы с печатью значений. В настоящее время пытается:

foreach my $date (keys %data) { 
    print OUT $date; 
    foreach my $id (@ids) { 
     foreach my $s (keys %{$data{$date}}) { 
      if (exists($data{$date}{$id})) { 
       print OUT ",", $data{$date}{$id} 
       } 
      else { 
       print OUT ","; 
       } 
      } 
     } 
    print OUT "\n"; # close printing on a given date 
    } 

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

$VAR1 = { 
    'date,time' => [ 
        'ID1' => [ 
          '0.00' 
          ] 
        'ID2' => [ 
          '0.12', 
          ] 
        'ID3' => [ 
          '0.17', 
          ] 
        'ID4' => [ 
          '0.22', 
          ] 
        ] 
      } 
    }; 

и печатная продукция, как это:

date,time,ARRAY(0x7f91c1030f60),ARRAY(0x7f91c1030f60),ARRAY(0x7f91c1030f60),ARRAY(0x7f91c1030f60) 

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

+0

Ваше описание очень неясно. Есть ли только один «Тема» для всего файла? Почему вы хотите, чтобы он повторялся четыре раза? Какие поля можно использовать в качестве ключей? например строка 'Data1' одинакова каждый раз? Является ли 'Date' фактической датой или это строка' 'Date''? Это позволило бы увидеть некоторые реальные данные, если это возможно. – Borodin

+0

«Объект» - это первый элемент в строке в файле данных. Мой текущий скрипт использует это, чтобы распознать, что это строка, содержащая список идентификаторов. «Дата» и «Время» являются заполнителями в примере для фактической даты и временных меток. Строки для каждого из четырех типов данных одинаковы в каждом блоке данных, как указано выше, используя заполнители «Data1» через «Data4». Идентификаторы субъектов, указанные выше, были представлены как «ID1», «ID2» и т. Д. - для этого явным образом отредактируйте это. –

ответ

1

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

Программа ожидает имя входного файла в качестве параметра командной строки и по умолчанию data.csv, если ни один из них не был отправлен. Он устанавливает $/ в пустую строку, чтобы включить «режим абзаца» в Perl, где данные считываются до следующей пустой строки или конца файла. Это означает, что все данные за данный временной интервал считываются сразу и должны быть разделены на отдельные строки перед обработкой.

use strict; 
use warnings; 

my ($subject, @ids); 
my @sort_order; 
my (%data, @keys); 

my ($file) = @ARGV; 
$file //= 'data.csv'; 

open my $fh, '<', $file or die qq{Unable to open file "$file" for reading: $!}; 
local $/ = ''; 
while (<$fh>) { 

    my @rows = split /\n/; 

    unless ($subject) { 
    ($subject, @ids) = split /,/, $rows[1]; 
    @sort_order = sort { $ids[$a] cmp $ids[$b] } 0 .. $#ids; 
    next; 
    } 

    my ($date, $time) = split /,/, shift @rows; 
    for (@rows) { 
    my ($id, @fields) = split /,/; 
    push @keys, $id unless exists $data{$id}; 
    push @{ $data{$id} }, [$date, $time, @fields[@sort_order]]; 
    } 
} 

for my $key (@keys) { 
    print join(',', $key, $subject, @ids[@sort_order]), "\n"; 
    print join(',', @$_), "\n" for @{ $data{$key} }; 
    print "\n"; 
} 

выход

Data1,Subject,ID#,ID1,ID2,[...] 
Date,Time1,aa#,aa1,aa2,[...] 
Date,Time2,ab#,ab1,ab2,[...] 

Data2,Subject,ID#,ID1,ID2,[...] 
Date,Time1,ba#,ba1,ba2,[...] 
Date,Time2,bb#,bb1,bb2,[...] 

Data3,Subject,ID#,ID1,ID2,[...] 
Date,Time1,ca#,ca1,ca2,[...] 
Date,Time2,cb#,cb1,cb2,[...] 

Data4,Subject,ID#,ID1,ID2,[...] 
Date,Time1,da#,da1,da2,[...] 
Date,Time2,db#,db1,db2,[...] 
+0

Я адаптировал это в своем скрипте (который в настоящее время читается по очереди). Результат такой же, как и желаемый, и он проще, чем то, что я делал. Однако вывод точно совпадает с моим текущим скриптом: сортировки нет. Если я изменю порядок идентификаторов объекта (например, переместите ID1 в конец, после ID #), строка темы будет изменена, но данные не будут повторно упорядочены. –

+0

Снова вы не дали мне ничего с чем поработать. Что такое * ID1, ID2 и т. Д. Являются ли они буквальными строками, которые появляются в данных, или они являются заполнителями для реальных идентификаторов. Если последнее, то какая форма принимает идентификаторы и как вы хотите их сортировать? – Borodin

+0

ID (ID1, ID2 и т. Д.) Являются буквенно-цифровыми, введенными кем-то, кроме меня, и не находятся под моим контролем. Это то, что человек, использующий тест, использует для идентификации предметов. Сортировка предназначена для буквенно-цифровых (сортировка {$ a cmp $ b}). См. Расширенный ответ ниже. –

0

Вы рассматривали ввод данных в базу данных SQL? [например. «server less» SQLite]

Это может быть перебор, но он должен предложить вам гораздо лучшую гибкость с большими наборами данных.

+0

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

+0

Пакет DB_File, предоставляемый «btree (file) as hash», будет приемлемым? Это даст вам ключ-сортированный хеш. – AnFi

Смежные вопросы