假设我们有一个数组,
arr = np.random.rand(3,3)
通常在将函数映射到数组时,我们只对数组元素的值感兴趣,即
f = lambda val : val**2
arr_squared = f(arr)
但是如果函数的输出取决于输入值在数组中的位置,即
,该怎么办?f = lambda x,y,val : x*y*val
现在我使用网格和ravel。
X, Y = np.arange(arr.shape[0]), np.arange(arr.shape[1])
X, Y = np.meshgrid(X,Y)
result = np.zeros(arr.shape)
for x,y in zip(np.ravel(X), np.ravel(Y)):
result[x,y] = f(x,y,arr[x,y])
这很有效,但速度很慢。我很难搞清楚是否有更好/更快的方法来做到这一点,在线搜索并没有产生太多有用的信息。
答案 0 :(得分:0)
原则上,索引的行为与任何其他参数一样。
这一切都归结为你的功能是否被矢量化。
如果是,请按照您的示例:
System.Windows.Forms.Timer
如果没有,例如</ p>
>>> Y, X = np.ogrid[(*map(slice, arr.shape),)]
>>> def f(X, Y, val): return X*Y*val
...
>>> f(X, Y, arr)
array([[0. , 0. , 0. ],
[0. , 0.92796409, 0.20353397],
[0. , 1.01294541, 1.30677315]])
快速修复是np.vectorize,但这并不快:
>>> def g(X, Y, val): return X+Y if val>0.5 else X-Y
...
>>> g(X, Y, arr)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in g
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
如果可能,最好手动矢量化:
>>> np.vectorize(g)(X, Y, arr)
array([[0, 1, 2],
[1, 2, 1],
[2, 3, 0]])
侧面注意你对meshgrid的使用:对于索引,你可以使用
来缩写它>>> def gv(X, Y, val): return X + (2*(val>0.5)-1) * Y
...
>>> gv(X, Y, arr)
array([[0, 1, 2],
[1, 2, 1],
[2, 3, 0]])
在上面的示例中,我使用了开放网格,利用广播来节省内存。