我已经构建了几个脚本来组织测试设备的数据输出,但我遇到了这个心理障碍。
测试设备监控来自多个受试者(具有标识符 ID1、ID2 等)的四种类型的输入(Data1、Data2、Data3、Data4),并以日期和时间戳为间隔记录每一种输入。设备转储的 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#
...等等。
“开始”将此行标识为数据的开头;“主题”将该行标识为包含主题 ID 的行;“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”只是简单地用作列标题。)
目前我通过将每一行放入一个单独的数组来做到这一点。这是一种快速而肮脏的完成工作的方式。该脚本获取时间和日期,并将 ID 行推入四个数组中的每一个(每种数据类型一个),然后根据数据类型依次添加每个数据行。输出只是逐行打印每个数组,添加一个空白行,然后打印下一个数组。这可行,但理想情况下,我想按主题 ID 对数据列进行排序,然后打印出数据,而不会丢失按日期和时间戳进行的垂直排序。(因为数据已经垂直排序,所以我目前在打印之前对数组没有排序功能。)
最简单的方法是什么?在精神上,我在尝试解析如何将 Y 行、X 列中的数据与 CSV 文件中 X 列中的主题 ID 相关联时遇到了麻烦。我使用的所有其他数据输出文件要么将主题 ID 作为每行中的第一项,要么每个主题有一个文件,这样更容易。
注意:因为时间/日期在他们自己的行上,我为每个使用一个变量;如果脚本检测到包含新时间和/或日期的行,它会更新变量值。
编辑——我采纳了 Borodin 的一些建议(让 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
}
继续获取垃圾输出(打印哈希引用,而不是实际值!)。Dumper 输出如下所示:
$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)
抱歉,到目前为止的示例一直在解释上造成问题。输入文件中有很多多余的数据和文本,我只包含了我试图提取和排序的部分的高度简化版本。