【问题标题】:How can I organize data in rows and columns with Perl?如何使用 Perl 按行和列组织数据?
【发布时间】:2022-01-28 00:35:22
【问题描述】:

基本问题是我有很多具有标准化名称的数据点,这些数据点刚刚从服务器转储到文件中,但我需要根据它们包含的数据自动将这些数据点组织到具有行和列的文件中(以它们的标准化名称表示)。


包含所有数据点的原始文件如下(这些不是原始数据点标签,而是简化的标签):

temp_r301
airflow_r301
temp_r345
airflow_r345
solar_w
solar_e
...

如您所见,它们都以一列的形式出现,因此每行有一个标签。

我想对它们进行组织,以便对于每个状态(“温度”,如温度),我在同一行中有相应的信息,例如:

temp_r301 301 airflow_r301 solar_w solar_e     #airflow in 301 and general solar radiation affect temperature (state) in room 301
temp_r345 345 airflow_r345 solar_w solar_e     #airflow in 345 and general solar radiation affect temperature (state) in room 345

当然,数组的长度可能会有所不同,因此我们的想法是制定一种算法来检测长度并相应地组织数据。另外,我知道我必须使用正则表达式来查找匹配项并定义哪些数据点是状态,哪些是输入,以及知道它们所属的房间。


到目前为止,我已经尝试了以下方法:

use strict;
use warnings;
use diagnostics;

my @transpose = ();
my @sorted = ();

push(@sorted, [qw(temp_r301 temp_r345)]);
push(@sorted, [qw(301 345)]);
push(@sorted, [qw(airflow_r301 airflow_r345 solar_w solar_e)]);

for my $sorted (@sorted) {
  for my $column (0 .. $#sorted) {
    push(@{$transpose[$column]}, $sorted->[$column]);
  }
}

for my $new_row (@transpose) {
  for my $new_col (@{$new_row}) {
      print "$new_col ";
  }
  print "\n";
}

但这只有在所有数组都具有相同长度的情况下才能正常工作(不是这种情况)。

我还发现了一个循环,可用于将数据存储为矩阵形式(数组的数组),但我似乎仍然无法找到将来自不同数组的数据写入矩阵的解决方案:

use strict;
use warnings;
use diagnostics;
use feature 'say';

my @states = qw(temp_r301 temp_r345);
my @zones = qw(301 345);
my @inputs = qw(airflow_r301 airflow_r345 solar_w solar_e);

my @matrix = ();

for my $x (0 .. $#states) {
    for my $y (0 .. $#inputs) {
        $matrix[$x][$y] = $states[$x];           #of course this only copies the states array and
    }                                            #repeats it for each created array
}

for my $aref (@matrix) {                         #print array of arrays
    say "[ @$aref ],";
}

那么,知道我已将所有数据转储到输入文件中,将这些数据排序到矩阵中的最佳方法是什么?有没有我应该更加注意的循环?我应该使用数组吗?

【问题讨论】:

  • 什么规则决定了@disturb的元素是否应该包含在给定的状态中?
  • @Matthias 感谢您的回复。那么我在上面的评论中提出的问题怎么样,有一个逗号/制表符分隔的文件和列出的列?然后每一行确实是您作为示例显示的内容,其中输入数据中缺少的字段将只是空的。这似乎(在我看来)是你需要的?
  • @Matthias 好的,谢谢。数据操作不是问题,问题是关于理解你想要做什么。那么,输入文件中的数据看起来如何?问题中没有显示,而是数组是(在我假设读取数据之后)。您可以从输入文件中添加几行到问题中吗?我当然可以使用这些数组,但是如果您确实有要处理的文件,那么最好使用它。
  • 谢谢!还有一个问题,在我发布一些内容之前:在您显示的数据中,如何判断solar_X 是否影响房间 301 或 345,或两者兼而有之,或其他...? (在这个例子中,它出现在 301 和 345 之后(紧跟在 345 之后),但我怀疑这是一个通用标准?)所有其他短语都有房间号,所以它们很容易组织,但 solar_X 什么都没有,并且很可能还有其他短语/变量中没有房间号。 (这也是@Shawn 一开始就问的问题。)
  • 回复this,您不是在尝试排序,而是在尝试分组。这通常使用哈希来完成。问题是不清楚你想如何分组。为什么 MET+EL____MEA+POW 与 LI____COM.POS+LI.INT+7.STEP (301,4,9; 345,19,24) 分组?如果是“情况就是这样”,我们需要知道这些关联的列表。这就是“受其影响”吗?如果是这样,我将首先创建一个影响受影响事物的哈希映射事物。我会使用push @{ $grouped{$room}{$thing_affected} }, $.; 对这些内容进行分组

标签: arrays perl


【解决方案1】:

这个问题的细节还不清楚,但解释确实有帮助。所以这就是我的假设。

我获取数据以使每行有一条信息。有些包含一个标签(描述),后跟房间号,我假设格式为tag_rN,标识标签适用的房间号。

对于没有房间号的其他人,需要进行额外处理来确定该信息所属的位置。这个问题只提出了一个适用于所有房间的标签示例,与影响它们的太阳辐射有关(参见 cmets),所以这就是所有已处理的内容。

某些数据没有整齐地与房间分类这一事实使得解析数据的组织变得不重要。由于没有给出详细信息,我只是将其分成两个散列,一个按房间号,另一个根据具体结构而定。

use warnings;
use strict;
use feature 'say';
use Data::Dump qw(dd);

my $file = shift // die "Usage: $0 file\n";
open my $fh, '<', $file or die "Can't open $file: $!";

my (%room, %other);
while (<$fh>) { 
    chomp;
    if ( my ($tag, $room_num) = /([^_]+)_r([0-9]+)/ ) {
        $room{$room_num}{$tag} = $_;                  # have room number
    }
    else {                                            # more processing needed
        my ($tag, $value) = parse_line($_);
        push @{ $other{$tag} }, $value;
    }
}
dd \%room; dd \%other; say '';

# Print in CSV format. Header first
my @tags = ( keys %{ $room{ (keys %room)[0] } }, keys %other );
say join ',', 'room', @tags;
foreach my $rnum (keys %room) { 
    say join ',', 
        $rnum, map { $room{$rnum}{$_} // join ' ', @{$other{$_}}  } @tags;
}

sub parse_line {
    my ($line) = @_;
    my ($tag, $value);

    if ($line =~ /solar_w|solar_e/) {   # example from sample data
        $tag   = 'solar';
        $value = $line;
    }
    else { }  # other possibilities

    return $tag, $value;
}

带有房间号的数据以标识描述(“标签”)为键排序,行为其值。每个这样的键值对都在分配给每个房间号的 hashref 中。

没有房间号的数据在一个单独的子中被解析,只有一些令牌代码,因为没有给出细节。然后将其存储在另一个哈希中,以便于操作(因为它不绑定到任何一个房间)。

如何从数据中提取标签有点随意,因为问题中没有指定。

所有这些都组合成 CSV 格式。以上,带有来自问题的输入文件和 cmets 中的解释,即来自西方和东方的太阳辐射会影响所有房间,打印:

{
  301 => { airflow => "airflow_r301", temp => "temp_r301" },
  345 => { airflow => "airflow_r345", temp => "temp_r345" },
}
{ solar => ["solar_w", "solar_e"] }

room,airflow,temp,solar
345,airflow_r345,temp_r345,solar_w solar_e
301,airflow_r301,temp_r301,solar_w solar_e

dd ...(来自Data::Dump)注释掉该行以删除初始诊断打印。然后最后几行是CSV,将进入某个文件等。

某些房间的某些数据可能会丢失,还有更多的数据可能无法如此统一地分类。然后,根据需要,这些标题的字段在某些行中将是空的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-18
    • 1970-01-01
    • 2014-11-04
    • 2016-04-26
    • 2016-09-23
    • 1970-01-01
    相关资源
    最近更新 更多