Python 带有比较运算符的Numpy广播;循环迭代
我以两种方式实现了循环迭代函数:Python 带有比较运算符的Numpy广播;循环迭代,python,arrays,numpy,Python,Arrays,Numpy,我以两种方式实现了循环迭代函数: def Spin1(n, N) : # n - current state, N - highest state value = n + 1 case1 = (value > N) case2 = (value <= N) return case1 * 0 + case2 * value def Spin2(n, N) : value = n + 1 if value
def Spin1(n, N) : # n - current state, N - highest state
value = n + 1
case1 = (value > N)
case2 = (value <= N)
return case1 * 0 + case2 * value
def Spin2(n, N) :
value = n + 1
if value > N :
return 0
else : return value
它神奇地工作了,真是太甜蜜了。所以我完全明白我想要什么:
[[0 0 0 0]
[0 0 5 0]
[0 0 0 0]]
[[1 1 1 1]
[1 1 0 1]
[1 1 1 1]]
现在,第二个函数print Spin2(AR1,5)
失败,出现以下错误:
if value > N
ValueError: The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()
原因很清楚,因为if-Array
语句是不存在的。所以现在我只使用了第一个变体。但是当我看这些函数时,我有一种强烈的感觉,在第一个函数中有更多的数学运算,所以我不会失去希望,我可以做一些优化它的事情。
问题:
1.是否可以优化功能
Spin1
以减少操作或如何在广播模式下使用功能Spin2
(可能不会使代码太难看)?额外问题:使用数组进行操作的最快方法是什么?
二,。是否有一些标准Python函数执行相同的计算(不支持隐式广播)以及如何正确地调用它——“循环增量” 这有一个numpy函数::
因此,您可以定义:
def Spin1(n, N) :
value = n + 1
return np.where(value > N, 0, value)
NumPy还提供了一种将普通Python函数转换为以下函数的方法: 现在,您可以在阵列上调用
Spin2
:
In [595]: Spin2(AR1, 5)
Out[595]:
array([[1, 1, 1, 1],
[1, 1, 0, 1],
[1, 1, 1, 1]])
然而,np.vectorize主要提供语法上的糖分。每个数组元素仍有一个Python函数调用,这使得
np.vectoriated
ufuncs。您的Spin1
遵循面向数组语言(如APL、MATLAB)中的一个既定模式,对Spin2
之类的函数进行“矢量化”。创建一个或多个布尔(或0/1数组)来表示数组元素可以采取的各种状态,然后通过乘法和求和构造输出
例如,为了避免被零除的问题,我使用了:
1/(x+(x==0))
一种变体是使用布尔索引数组来选择应该更改的数组元素。在这种情况下,您希望返回值
,但所选元素“已滚动”
def Spin3(n, N) : # n - current state, N - highest state
value = n + 1
value[value>N] = 0
return value
在这种情况下,索引方法更简单,似乎更适合程序逻辑。它可能更快,但我不能保证。最好记住这两种方法。我在这里给出了一些反馈作为答案,只是不想把问题搞砸。因此,我对各种函数进行了计时测试,结果表明,在这种情况下,通过布尔掩码赋值是最快的变量(hpaulj的答案)<代码>np。其中慢了1.4倍,
np。矢量化(Spin2)
慢了15倍。现在出于好奇,我想用循环来测试这个,所以我制定了这个算法来测试:
AR1 = numpy.zeros((rows, cols), dtype = numpy.uint32)
while d <= 100:
Buf = numpy.zeros_like(AR1)
r = 0
c = 0
while (r < rows) :
while (c < cols) :
temp = AR1[r, c] + 1
if temp > 5 :
Buf[r, c] = 1
else : Buf[r, c] = temp
c += 1
r += 1
c = 0
AR1 = Buf
d += 1
AR1=numpy.zero((行,列),dtype=numpy.uint32)
d 5:
Buf[r,c]=1
其他:Buf[r,c]=温度
c+=1
r+=1
c=0
AR1=Buf
d+=1
我不确定,但似乎上述所有功能的实现都非常简单。但是它太慢了,几乎慢了300倍。我读过类似的问题,但我还是不明白,为什么会这样?到底是什么导致了这种减速。在这里,我特意创建了一个缓冲区,以避免相同元素上的读写函数,并且不进行内存清理。那么,还有什么比这更简单,我感到困惑。不想打开一个新问题,因为它已经被问了几次,所以可能有人会发表评论或有好的链接来澄清这一点 非常感谢,+1表示
np。其中
与我的函数完全相同。是的,这正是我所想的。所以我想我该如何在没有索引的情况下为这个布尔掩码定义的元素做一些事情。你的变体看起来最适合我,它很清晰,很适合我的任务,因为我现在做了很多图像处理,而且都是关于位掩码的。我刚刚发现了另一个类似的numpy函数np.putmask
,它也可以用于在位掩码中混合数组。
1/(x+(x==0))
def Spin3(n, N) : # n - current state, N - highest state
value = n + 1
value[value>N] = 0
return value
AR1 = numpy.zeros((rows, cols), dtype = numpy.uint32)
while d <= 100:
Buf = numpy.zeros_like(AR1)
r = 0
c = 0
while (r < rows) :
while (c < cols) :
temp = AR1[r, c] + 1
if temp > 5 :
Buf[r, c] = 1
else : Buf[r, c] = temp
c += 1
r += 1
c = 0
AR1 = Buf
d += 1