是否有一种在NumPy中对这些操作进行矢量化的一般方法?
In [2]: N = 8
In [3]: ll = np.arange(8)
In [4]: arr = np.zeros(ll.shape + (2, 2))
In [5]: ll.shape
Out[5]: (8,)
In [6]: arr.shape
Out[6]: (8, 2, 2)
In [7]: for ii in range(N):
...: arr[ii, :, :] = np.array(...) # 2 x 2 array function of ll[ii]
如果该函数是ll上的线性运算那么这将是微不足道的,但是在一般情况下有没有办法做到这一点?举个例子:
In [8]: for ii in range(N):
...: arr[ii, :, :] = np.array([
...: [np.cos(ll[ii]) - 1, 0],
...: [np.sin(ll[ii]), np.cos(ll[ii]) ** 2]
...: ])
答案 0 :(得分:5)
组装arr
数组的正确方法如下:
arr[:, 0, 0] = np.cos(ll) - 1
arr[:, 0, 1] = 0
arr[:, 1, 0] = np.sin(ll)
arr[:, 1, 1] = np.cos(ll) ** 2
你绝对不应该在将要存储在已经存在的数组中的数组列表上调用np.array
:这是一个浪费的中间数组创建,这是一个不好的做法,我怀疑它增加了任何清晰度到代码。有记忆/性能的开发人员可能会做类似的事情:
np.cos(ll, out=arr[:, 0, 0])
arr[:, 1, 1] = arr[:, 0, 0]
arr[:, 0, 0] -= 1
arr[:, 0, 1] = 0
np.sin(ll, out=arr[:, 1, 0])
arr[:, 1, 1] *= arr[:, 1, 1]
但这通常属于不成熟的优化类别。
你也应该真的不使用ll
作为变量名......
答案 1 :(得分:1)
你可以这样做:
def func(x):
return np.array([
[np.cos(x)-1,np.repeat(0, len(x))],
[np.sin(x), np.cos(x)**2]
])
然后func(x)
将返回一个形状(2, 2, 8)
的数组。您可以使用func(x).T
以所需的方向获取它。
仅当x
为一维时才有效。我认为你可以使用np.broadcast_arrays
为更高维度工作,但目前还不确定。但基本的是,如果你想返回一个数组,你不能在某些单元格中使用像cos
这样的矢量化numpy函数,而在其他单元格中放置文字标量(如0)。您需要使用一个数组填充标量单元格,该数组的形状来自输入数组。