【问题标题】:Numpy: vectorizing two-branch test (ternary-operator like)Numpy:向量化两分支测试(三元运算符)
【发布时间】:2016-03-16 11:20:48
【问题描述】:

为了以下想法,我在 Numpy 中对测试进行矢量化:执行 elementwise 一些测试并根据测试选择 expr1expr2。这就像 C 中的 三元运算符test?expr1:expr2

我看到了两种主要的执行方式;我想知道是否有充分的理由选择一个而不是另一个;也许还有其他技巧可用,我很高兴知道它们。主要目标是速度;出于这个原因,我不想将np.vectorizeif-else 语句一起使用。

对于我的例子,我将重新构建min 函数;请不要告诉我一些用于计算的 Numpy 函数;这只是一个例子!

想法1:在乘法中使用布尔值的算术值:

# a and b have similar shape
test = a < b
ntest = np.logical_not(test)
out = test*a + ntest*b

想法 2:或多或少遵循 APL/J 编码风格(通过使用条件表达式作为比初始数组多一维的数组的索引)。

# a and b have similar shape
np.choose(a<b, np.array([b,a]))

【问题讨论】:

    标签: python numpy conditional ternary-operator


    【解决方案1】:

    这是使用choose的更好方法

    np.choose(a<b, [b,a])
    

    在我的小时间里,它更快。 choose 文档还说 Ifchoicesis itself an array (not recommended), ....

    (a<b).choose([b,a])
    

    保存一级函数重定向。

    另一种选择:

    out = b.copy(); out[test] = a[test]
    

    在快速测试中,这实际上更快。 masked.filled 使用 np.copyto 进行这种“位置”复制,尽管它似乎并没有更快。

    choose 的一个变体是where

    np.where(test,a,b)
    

    或使用where(或np.nonzero)将布尔索引转换为数字索引:

    I = np.where(test); out = b.copy(); out[I] = a[I]
    

    由于某种原因,这比单件要快。

    我过去使用过乘法方法;如果我没记错的话,即使是 APL(尽管那是几十年前的事了)。避免除以 0 的一个老技巧是添加 n==0a/(b+(b==0))。但它并不普遍适用。 a*0, a*1 必须有意义。

    choose 看起来不错,但使用mode 参数可能会更强大(因此也更复杂)。

    我不确定是否有“最佳”方式。时序测试可以评估某些情况,但我不知道它们可以在所有情况下推广到哪里。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-26
      • 2011-12-12
      • 2019-05-06
      • 2014-10-10
      • 1970-01-01
      • 2021-01-25
      • 2017-08-28
      相关资源
      最近更新 更多