【问题标题】:PDL pairwise row comparisonPDL 成对行比较
【发布时间】:2012-01-25 14:02:32
【问题描述】:

我创建了一个 PDL 矩阵。我需要在每一行之间进行成对比较。目前我正在使用“where”和“cov”命令返回两个切片的成对比较(在 perl 循环中生成)。

我的问题:如何使用“范围”和“切片”以成对的方式遍历行?如何返回我的索引位置?我已经使用 perl 遍历了矩阵。我读过用 perl 循环真的削弱了 PDL 的力量。

期望的输出:

indexA indexB Value
pos1   pos5   1
pos1   pos6   5
pos1   pos0   7 

明确地说,我只想使用 PDL 功能。

这里有一些伪代码(希望)能更好地说明我的观点。

p $b

[
 [1 0 3 0]
 [0 1 0 1]
 [1 3 1 3]   <- example piddle y
 [0 1 0 1]   <- example piddle z
]

my concept function{


slice $b (grab row z) - works fine
slice $b (grab row y) - works fine


($a, $b) = where($a,$b, $a < 3 && $b < 3 ) - works fine

p $a [1 1] 
p $b [0  0] 

cov($a $b) - works just fine.

}

我只需要一种在所有行中成对执行的方法。我需要进行阶乘(n 行)比较。

【问题讨论】:

  • 绝望...我现在正在写一个perl循环,但很遗憾。
  • 我不太确定你在说什么。你能举一个更具体的例子来说明你正在使用的数据吗?

标签: perl pdl


【解决方案1】:

PDL 线程是您在此处寻找的概念。沿维度循环的一般技术是在适当的位置添加 dummy 维度,以便计算生成所需的隐式线程循环。对于多维问题,可以有多种不同的方法来添加暗淡,从而创建线程循环。

对于成对行计算,您可以在切片索引上选择两个嵌套循环,该循环在两个索引计数上具有 perl 循环,并将沿行生成 PDL 线程。您可以只对索引使用一个 perl 循环,但可以利用隐式线程循环一次计算所有行。

完全 PDL 线程循环计算是为每个参数的行上的循环添加一个虚拟维度,以便您一次计算整个 N**2 行计算。这是一个形状 [4,3] 数组的示例,其计算是 == 运算符:

pdl> $b = floor(random(4,3)*5)

pdl> p $b

[
 [0 4 3 3]
 [3 3 4 2]
 [4 0 1 4]
]

pdl> p $b(,*3)==$b(,,*3)

[
 [
  [1 1 1 1]
  [0 0 0 0]
  [0 0 0 0]
 ]
 [
  [0 0 0 0]
  [1 1 1 1]
  [0 0 0 0]
 ]
 [
  [0 0 0 0]
  [0 0 0 0]
  [1 1 1 1]
 ]
]

结果是一个形状 [4,3,3] piddle,第 0 维对应于成对计算产生的行,第 1 和第 2 维对应于 == 操作中涉及的行索引。

如果您需要来自或用于这些线程循环计算之一的索引值,请使用 xvalsyvalszvalsaxisvals 生成一个带有与该数组轴对应的索引值的 piddle。

pdl> p $b->xvals

[
 [0 1 2 3]
 [0 1 2 3]
 [0 1 2 3]
]


pdl> p $b->yvals

[
 [0 0 0 0]
 [1 1 1 1]
 [2 2 2 2]
]

关于 PDL 线程的实现有很多细节(与 perl 线程或 posix 线程不同)。我推荐perldl mailing list 供其他 PDL 用户和开发人员参考和讨论。另外,请参阅PDL Book 的第一个在线草稿,它更全面地涵盖了 PDL 计算和线程。

【讨论】:

    【解决方案2】:

    我认为您正在寻找的是一种方法来查找数组中所有不同的行对,然后使用cov 处理每一对?如果这是正确的,那么我还没有听说过cov,并且快速搜索文档也无济于事。不过,我可以说一些可能会有所帮助的事情。

    我认为您在将PDL 退出到 Perl 代码中时过于谨慎了,如果您所做的只是循环所有行对的索引并使用 slice 将这些行拉出,那将很好。这显示在下面的一些示例代码中。

    您也不能像 $a &lt; 3 等那样调用 where 等本身就是 piddles 并且布尔运算符不会对它们执行您想要的操作。请改用&amp; 运算符,并添加一些括号以确保表达式以正确的顺序执行。

    除此之外,除非您纠正我对您的问题的理解或指导我查看 cov 子例程的一些文档,否则我无能为力。

    use strict;
    use warnings;
    
    use PDL;
    
    my $dat = pdl <<END;
    [
     [1 0 3 0]
     [0 1 0 1]
     [1 3 1 3]
     [0 1 0 1]
    ]
    END
    
    my $max2 = $dat->dim(1) - 1;
    
    for my $i (0 .. $max2 - 1) {
      for my $j ($i + 1 .. $max2) {
    
        my $row1 = $dat->slice(",($i)");
        my $row2 = $dat->slice(",($j)");
    
        ($row1, $row2) = where($row1, $row2, ($row1 < 3) & ($row2 < 3));
    
        cov($row1, $row2);
      }
    }
    

    【讨论】:

    • 请注意,您初始化$dat 的方式可能会更加简洁。你不需要heredoc。只需使用多行字符串。 cmets 中缺少换行符使其变得困难,但是如果您只是将字母 q 放在左方括号前面并删除heredoc cruft,它会正常工作:$dat = q[ 1 0 3 0; 0 1 0 1; 1 3 1 3; 0 1 0 1]; 请注意q 就在方括号将方括号转换为 Perl 引号,同时保持意图。
    • @DavidMertens:我知道 Perl 引号是如何工作的。我使用了一个heredoc,这样我就可以直接从问题中复制数据
    • 可以使用q 运算符直接从问题中复制数据。见pdl.perl.org/PDLdocs/Core.html#pdl
    • @DavidMertens:可以使用qq 运算符引用任何内容。为什么你认为 heredocs 存在?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-22
    • 2012-09-22
    • 1970-01-01
    • 1970-01-01
    • 2022-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多