【问题标题】:Perl - Returning the maximum value in a data setPerl - 返回数据集中的最大值
【发布时间】:2012-08-20 04:43:41
【问题描述】:

我以前从未深入研究过 Perl 的世界,我觉得它很混乱,需要一些帮助。在下面的代码中, calc() 部分返回“输入”超过“计数”样本的运行平均值。我想修改它,以便 calc() 返回样本集中的最大值。提前感谢您的帮助!

sub calc
{
    my ($this, $dim, $input, $count) = @_;

    if ($count < 1)
    {
        warn "count=$count is less than 1.";
        return undef;
    }

    my $inputsum_in = $this->{inputsum};
    my ($inputcumsum, $inputsum_out) = PDL::CumulativeSumOver2($input, $inputsum_in);

    my $inputdelay = $this->delay('inputhistory', $input);
    my $inputdelaysum_in = $this->{inputdelaysum};
    my ($inputdelaycumsum, $inputdelaysum_out) = PDL::CumulativeSumOver2($inputdelay, $inputdelaysum_in);

    $this->{inputsum} = $inputsum_out;
    $this->{inputdelaysum} = $inputdelaysum_out;

    my $sampleno = $this->{sampleno};
    my $divider = $count;
    if($sampleno < $count)
    {
        my $last = $dim - 1;
        $divider = sequence($dim) + ($sampleno + 1);
        my $start = $count - $sampleno;
        $divider->slice("$start:$last") .= $count if $start <= $last;
        $this->{sampleno} = $sampleno + $dim;
    }
    return ($inputcumsum - $inputdelaycumsum) / $divider;
}

【问题讨论】:

  • 感谢您的反馈。在上面的代码中,'$input' 来自每 100 毫秒读取一次的传感器,因此无论有多少样本('$count'),我都选择查看返回的最大值。我认为 return max($data_set);会很好。我只是不知道如何从“$input”生成数据集。数据集需要不断更新新的输入,同时丢弃最旧的数据。 perl 解释器内置在汽车诊断软件中,因此 calc() 上面的方法就是它需要完成的方式。
  • 好吧,我已经脱离了 PDL 的元素。我假设会有一个 max() 函数并用谷歌搜索它。但至于从数据中创建 piddles,我最终会为您阅读 PDL 文档。
  • “max”方法适用于任何 PDL 对象。如果你“使用 PDL”,max 也是一个导入到你当前包中的函数。看起来编写您的代码的人对 PDL 了解一两件事,而获得 PDL 答案的最佳地点是加入 Perldl 邮件列表:mailman.jach.hawaii.edu/mailman/listinfo/perldl

标签: perl pdl


【解决方案1】:

怎么样

 $max = max($input);

PDL Primitives

【讨论】:

    【解决方案2】:

    如果你想找到某个值列表的最大值,你不需要编写你自己的子程序。 perl v5.7.3 或更高版本已经附带了一个函数:

    use List::Util qw(max); # core module since v5.7.3
    use strict;
    use warnings;
    
    print max(1 .. 10);  # prints 10
    

    【讨论】:

    • 他的代码已经使用了 PDL。所以 $input 很可能会成为一个“谜题”而不是一个列表/数组。
    • 根据我的经验,List::UtilPDL 不能很好地配合使用。 PDL 定义了maxmin,因此use 使用List::Util 版本的max 和min 会导致解释器拒绝运行您的脚本。
    【解决方案3】:

    编辑:这是我认为你需要的循环。

    1. 从传感器读取输入数据
    2. 将新数据附加到存储的数据中
    3. 丢弃多余的数据
    4. 评估

    这就是我的做法。

    my $storedData = pdl;  
    # $storedData is now a vector containing one element, 0
    while (! stopCondition()) {
        my $input = readSensorData(); # step 1
        $storedData = $storedData->append($input); # step 2
        if ($storedData->nelem > $count) { # step 3
            $storedData = $storedData->slice("-$count:-1");
            # note that -1 points to the last element in a piddle and -X refers to 
            # the element X-1  away from the end (true for piddles and native arrays)
        }
        my ($max, $min) = evaluate($storedData); # step 4
    }
    

    我不确定这是否能回答您的问题,但您下面的评论似乎与您上面的问题完全不同。考虑编辑以上内容以更好地反映您遇到的问题或提出新问题。


    获得运行平均值的一种简单方法是使用有限脉冲响应滤波器,也就是卷积。用(归一化)矩形脉冲对任何信号进行卷积,得到运行平均值。

    my $filter = ones($count) / $count; 
    my $runningAve = convolveND($input, $filter); 
    my $max = $runningAve->max`; 
    

    或者一行

    my $max = convolveND($input, ones($count) / $count)->max;
    

    convolveNDis documented here.


    使用此方法需要注意一件事,即 $runningAve 开头和结尾处的值并不是真正的运行平均值。为了确保输出与输入的大小相同convolveND(默认情况下)有效地将零连接到输入的开头和结尾,结果是$runningAve 的第一个和最后几个元素低于实际运行平均值。 (请注意,运行平均值原则上应该有N - (window - 1) 元素,N 是$input 的大小。)由于这些“坏”值必然低于实际运行平均值,它们不会干扰最大值你要。 (关于“默认情况下”:convolveND 有其他处理边缘的方法,正如您将在上面链接的文档中看到的那样。)

    (注意:我不是 PDL 专家。可能有一种比 convolveND 更便宜的方法来获得运行平均值,例如 $ra = $input-&gt;range(...)-&gt;sumover(0) / $count,但我不知道你会在.. . 上面是可读的。另见http://search.cpan.org/~jlapeyre/PDL-DSP-Iir-0.002/README.pod#moving_average)

    【讨论】:

    • 感谢您的回复。上面的代码示例已经计算了运行平均值。我需要的代码是从'my ($this, $dim, $input, $count) = @_;' 构建一个数据集存储 $count # of $input 值,同时在收到新的 $inputs 时弃用旧值。然后从那个数据集中我可以'返回 MAX(dataset);或 Min 根据需要。
    • 我并没有真正关注。如果您只想考虑$input 中的最新条目,您可以在$input-&gt;slice("-$count:-1") 上进行任何相关计算。如果你想把新东西加到旧东西上,只留下$count元素,那么你可以说$store = $old-&gt;append($new)-&gt;slice("-$count:-1")
    • 您可能会更新您的问题,因为您似乎还没有完全描述您需要什么。 (PS 反引号 ` 表示代码格式。)
    • 我的部分问题是我真的对 Perl 以及 Perl 如何处理数据的了解不够。它会自动将传入的数据存储为某种形式的数组吗?无论如何,尽管我的 Perl 无能,但这是我需要的(人类),它需要遵循我的 OP 中代码示例的结构 sub calc{....}
    • 在诊断软件中,用户将 $count(必须 >0)设置为要评估的输入值的数量。运行诊断时; 1. 从传感器获取 $input 2. 将 $input 添加到 $all_inputs 3. 如果 count($all_inputs) > $count 3a.然后:将最新的 ($all_inputs) 存储在 $inputs_to_eval 3b 中。否则:将所有 ($all_inputs) 存储在 $inputs_to_eval 4. 评估 $inputs_to_eval 并返回集合中的最小值或最大值。我什至无法弄清楚如何正确格式化此列表..... =/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    • 1970-01-01
    • 2018-09-28
    • 2013-06-05
    • 2011-11-15
    • 1970-01-01
    相关资源
    最近更新 更多