我正在尝试在Python中有效地索引2D数组,并且问题是它非常慢。
这就是我尝试过的(简化示例):
xSize = veryBigNumber
ySize = veryBigNumber
a = np.ones((xSize,ySize))
N = veryBigNumber
const = 1
for t in range(N):
for i in range(xSize):
for j in range(ySize):
a[i,j] *= f(i,j)*const # f(i,j) is an arbitrary function of i and j.
现在我想用更高效的东西替换嵌套循环。我该怎么做?
答案 0 :(得分:6)
您可以使用以下内容生成2D数组:
np.arange(200)[:,np.newaxis] + np.arange(200)
这种矢量化操作可能非常快:
>>> %timeit np.arange(200)[:,np.newaxis] + np.arange(200)
1000 loops, best of 3: 178 µs per loop
not 中的此方法仅限于添加。我们可以在上面的操作中使用两个数组作为任何universal function的参数(通常缩写为 ufunc )。
例如:
>>> np.multiply(np.arange(5)[:,np.newaxis], np.arange(5))
array([[ 0, 0, 0, 0, 0],
[ 0, 1, 2, 3, 4],
[ 0, 2, 4, 6, 8],
[ 0, 3, 6, 9, 12],
[ 0, 4, 8, 12, 16]])
NumPy为所有基本算术运算构建了ufunc,并且还有一些更有趣的运算。如果您需要更具异国情调的功能,NumPy allows you to make your own ufunc。
编辑:快速解释此方法中发生的广播;你能想到这样......
np.arange(5)
生成一维数组,如下所示:
array([0, 1, 2, 3, 4])
代码np.arange(5)[:,np.newaxis]
在范围中添加第二维(列),生成此2D数组:
array([[0],
[1],
[2],
[3],
[4]])
使用np.multiply
创建最终的5x5数组(尽管我们可以使用任何ufunc或二进制算术运算),NumPy在第二个数组中取0
并将其与第一个数组中的每个元素一起删除像这样排:
[ 0, 0, 0, 0, 0]
然后它接受第二个数组中的第二个元素1
,并将它与第一个数组相乘,产生这一行:
[ 0, 1, 2, 3, 4]
这一直持续到我们有最终的5x5矩阵。
答案 1 :(得分:5)
您可以使用indices
例程:
b=np.indices(a.shape)
a=b[0]+b[1]
<强>时序:强>
%%timeit
...: b=np.indices(a.shape)
...: c=b[0]+b[1]
1000 loops, best of 3: 370 µs per loop
%%timeit
for i in range(200):
for j in range(200):
a[i,j] = i + j
100 loops, best of 3: 10.4 ms per loop
答案 2 :(得分:1)
由于输出矩阵a
是矩阵F
的N的元素幂,其元素为f_ij = f(i,j) * const
,因此您的代码可以简化为
F = np.empty((xSize, ySize))
for i in range(xSize):
for j in range(ySize):
F[i,j] = f(i,j) * const
a = F ** n
为了更快的速度,你可以用更有效的东西来交换F
矩阵的创建,因为函数f(i,j)
是矢量化的:
xmap, ymap = numpy.meshgrid(range(xSize), range(ySize))
F = f(xmap, ymap) * const