Python Numpy:矢量化双分支测试(类似三值运算符)
我正在Numpy中对一个测试进行矢量化,以实现以下想法:执行一些元素级的测试,并根据测试选择expr1或expr2。这类似于C:Python Numpy:矢量化双分支测试(类似三值运算符),python,numpy,conditional,ternary-operator,Python,Numpy,Conditional,Ternary Operator,我正在Numpy中对一个测试进行矢量化,以实现以下想法:执行一些元素级的测试,并根据测试选择expr1或expr2。这类似于C:test?expr1:expr2 我认为有两种主要的方法可以实现这一点;我想知道是否有充分的理由选择其中一个而不是另一个;也许还有其他的技巧,我很高兴知道。主要目标是速度;因此,我不想使用np.vectorize和if-else语句 例如,我将重新构建min函数;求你了,不要告诉我一些计算它的Numpy函数;这仅仅是一个例子 想法1:在乘法中使用布尔值的算术值: # a
test?expr1:expr2
我认为有两种主要的方法可以实现这一点;我想知道是否有充分的理由选择其中一个而不是另一个;也许还有其他的技巧,我很高兴知道。主要目标是速度;因此,我不想使用np.vectorize
和if-else
语句
例如,我将重新构建min
函数;求你了,不要告诉我一些计算它的Numpy函数;这仅仅是一个例子
想法1:在乘法中使用布尔值的算术值:
# a and b have similar shape
test = a < b
ntest = np.logical_not(test)
out = test*a + ntest*b
#a和b的形状相似
试验=a
Idea 2:或多或少遵循APL/J编码风格(使用条件表达式作为比初始数组多一个维度的数组的索引)
#a和b的形状相似
这是使用choose
np.choose(a<b, [b,a])
保存一级函数重定向
另一种选择:
out = b.copy(); out[test] = a[test]
在快速测试中,这实际上更快。masked.filled
使用np.copyto
进行这种“where”复制,尽管它似乎没有更快
选择
的变体是其中
:
np.where(test,a,b)
或者使用where
(或np.nonzero
)将布尔索引转换为数字索引:
I = np.where(test); out = b.copy(); out[I] = a[I]
出于某种原因,这比单件式快了一倍
我过去曾使用过乘法方法;如果我能正确地回忆起APL(虽然那是几十年前的事)。避免被0除的一个老技巧是加n==0
,a/(b==0))
。但它并不普遍适用。a*0
,a*1
choose
看起来不错,但是使用模式
参数可能更强大(因此也更复杂)
我不确定是否有“最佳”的方法。计时测试可以评估某些情况,但我不知道它们可以推广到所有情况
np.where(test,a,b)
I = np.where(test); out = b.copy(); out[I] = a[I]