我正在尝试将较小的2D numpy数组(“源”)的值添加到较大的2D numpy数组(“ frame”)中,从帧数组中的特定位置(“ pos_x”,“铭文”)。现在,我有两个for循环将源值添加到每个位置的帧值:
for i in range(x):
for j in range(y):
frame[pos_x+i][pos_y+j] += source[i][j]
(“ x”和“ y”是源数组的形状)
但是,阵列很大(框架阵列形状:5000x8000,源阵列形状:1000x5000)。因此,此过程需要相当长的时间(约15秒)。
是否有任何方法可以通过列表理解,映射或其他方法来加快此过程?
我已经尝试过使用多个语句和赋值来进行列表理解:
frame = [[frame[pos_x+i][pos_y+j] + source[i][j] for j in range(y)] for i in range(x)]
(根据线程How can I do assignments in a list comprehension?和Multiple statements in list compherensions in Python?改编)
,但是它花的时间与原始for循环一样长。
另一个想法是只允许使用if source[i][j] != 0
循环非零值。但是当我尝试这样做时,它花费了三倍的时间(潜在的子问题:为什么知道?)。
答案 0 :(得分:1)
切片在numpy
中是可变的;因此您可以执行以下操作:
import numpy as np
A = np.zeros((10,10), int)
B = np.zeros((5,5), int) + 5
A[2:7,2:7] += B
print(A)
答案 1 :(得分:1)
您可以在这里利用numpy向量化,而无需循环进行大幅加速。只需计算索引并检查是否超出范围即可。
height, width = source.shape
pos_x2 = pos_x + width
pos_y2 = pos_y + height
#check for possible index out of range
fheight, fwidth = frame.shape
if pos_x2 > fwidth or pos_y2 > fheight:
print('source out of frame bounds')
else:
#add `source` to our slice of `frame`
frame[pos_y:pos_y2, pos_x:pos_x2] += source
从技术上讲,这将具有相同的时间复杂度,但numpy使用高效的已编译C代码,可以利用诸如硬件矢量化之类的优势,而没有python解释器的所有开销。