在numpy / regular python

时间:2016-01-28 13:50:42

标签: python numpy

美好的一天, 对于我的研究,我在2维中创建了细胞自动生成。该程序已经运行但我仍然尝试优化它。下面的代码段总结了2D阵列中的中心单元的所有8个相邻单元。之后,下一个单元被定义为总和的函数。 有没有比2 for-loops更快的方法?

之前我甚至有4个for循环用于求和,但它比现在慢2倍......

n = len(mat1)
m = len(mat1[0])
mat2 = np.zeros((n,m))
sumN = 0
start = time.time()
for i in range(1,n-1):  
    for j in range(1,m-1):
        sumN = mat1[i-1,j-1] + mat1[i-1,j] + mat1[i-1,j+1] + mat1[i,j-1] +mat1[i,j+1] + mat1[i+1,j] + mat1[i+1,j+1]+ mat1[i+1,j-1]
        if str(sumN) in B and mat1[i,j] == 0:
            mat2[i,j] = 1
        elif str(sumN) in S and mat1[i,j] == 1:
            mat2[i,j] = 1
        sumN = 0
end = time.time()
print end - start

感谢xnx,我将滚动包含在矩阵上,而不是遍历所有元素。之后我创建了一个布尔2D numpy数组,用于初始化下一代。

sumN = sum(np.roll(np.roll(mat1, i, 0), j, 1)
for i in (-1, 0, 1) for j in (-1, 0, 1)
  if (i != 0 or j != 0)).flatten()

mat1 = mat1.flatten()

b = np.array(map(lambda x,l: ((int(x) == 0) and (str(int(l)) in B)) 
   or ((int(x) == 1) and (str(int(l)) in S)), mat1,sumN)).reshape(n,m)                           
mat2 = np.zeros((n,m))                                                      
mat2[b] = 1                                                         
mat2 = mat2.reshape(n,m)

2 个答案:

答案 0 :(得分:1)

this blog article中提供了一种很好的方法:

nbrs_count = sum(np.roll(np.roll(mat1, i, 0), j, 1)
                 for i in (-1, 0, 1) for j in (-1, 0, 1)
                 if (i != 0 or j != 0))

这是有效的,因为numpy.roll(a, shift, axis)沿给定的轴移动元素axis,指定数量的地方shift进行换行,因此可以依次访问每个8个单元格如果您遍历行i=-1,0,1和列j=-1,0,1,但请注意不要计算中心单元本身。

答案 1 :(得分:0)

不确定这是否更快(您应该使用您的数据集检查它),但您尝试做的似乎接近图像处理。

Scikit图像是一个非常好的模块,并且有很好的机会比你的解决方案快得多,因为很多功能都是在C / Fortran中实现的。

from skimage.morphology import square
import skimage.filters.rank as rank
import numpy as np

sumN=rank.sum(mat1,square(3)) # sum of each pixels in a 3 pixel-sided square

# compare with B and S :
n,m =np.shape(mat1)
sumN=np.flatten(sumN) # vectorize your array to be faster
mat1=np.flatten(sumN)
mat2=np.zeros_like(mat1)
for i in range(len(mat1): # only looping on 1 variable is faster
    if str(sumN[i]) in B and mat1[i] == 0:
        mat2[i] = 1
    elif str(sumN[i]) in S and mat1[i] == 1:
        mat2[i] = 1
mat1=mat1.reshape(n,m) # go back to the previous shape
mat2=mat2.reshape(n,m)