Numpy:矢量化双分支测试(三元运算符)

时间:2015-12-10 17:42:13

标签: python numpy conditional ternary-operator

我正在Numpy中进行测试,以实现以下想法:执行 elementwise 一些测试,并根据测试选择 expr1 expr2 。这就像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]))

1 个答案:

答案 0 :(得分:3)

这是使用choose

的更好方法
np.choose(a<b, [b,a])

在我的小时间里,它更快。此外,choose文档说If个选项is itself an array (not recommended), ....

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

保存一级功能重定向。

另一种选择:

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

在快速测试中,这实际上更快。 masked.filled使用np.copyto作为此类'where'副本,但它似乎没有更快。

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*0a*1必须有意义。

choose看起来不错,但mode参数可能更强大(因而也很复杂)。

我不确定是否有'最好'的方式。时间测试可以评估某些情况,但我不知道它们可以在所有情况下推广到何处。