将依赖于其输入值位置的函数映射到numpy数组

时间:2018-03-18 08:50:00

标签: python arrays numpy dictionary mapping

假设我们有一个数组,

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])

这很有效,但速度很慢。我很难搞清楚是否有更好/更快的方法来做到这一点,在线搜索并没有产生太多有用的信息。

1 个答案:

答案 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]])

在上面的示例中,我使用了开放网格,利用广播来节省内存。