循环大型稀疏数组

时间:2016-07-22 22:01:23

标签: python arrays numpy scipy

假设我有一个(稀疏)矩阵M大小(N*N, N*N)。我想从这个矩阵中选择grid(一个(n,m)数组,其中n*m=N)为True的外积(它是一个布尔2D数组,na=grid.sum() )。这可以按如下方式完成

result = M[np.outer( grid.flatten(),grid.flatten() )].reshape (( N, N ) )

result是一个(na,na)稀疏数组(和na < N)。前一行是我想要实现的:从grid的乘积中获取M的元素,并从数组中挤出那些不正确的元素。

nm(以及N)增长,而Mresult是稀疏矩阵时,我无法有效地执行此操作在记忆或速度方面。我最近尝试的是:

result = sp.lil_matrix ( (1, N*N), dtype=np.float32 )
# Calculate outer product
A = np.einsum("i,j", grid.flatten(), grid.flatten())  
cntr = 0
it = np.nditer ( A, flags=['multi_index'] )
while not it.finished:
    if it[0]:
        result[0,cntr] = M[it.multi_index[0], it.multi_index[1]]
        cntr += 1
# reshape result to be a N*N sparse matrix

最后一次重塑可以由this approach完成,但我还没有到达那里,因为while循环需要永远。

我也尝试过选择A的非零元素,然后循环,但这会占用所有内存:

A=np.einsum("i,j", grid.flatten(), grid.flatten())  
nzero = A.nonzero() # This eats lots of memory
cntr = 0
for (i,j) in zip (*nzero):
    temp_mat[0,cntr] = M[i,j]
    cnt += 1
上面例子中的

'n'和'm'大约是300.

1 个答案:

答案 0 :(得分:1)

我不知道这是错字还是代码错误,但您的示例缺少iternext

R=[]
it = np.nditer ( A, flags=['multi_index'] )
while not it.finished:
    if it[0]:
        R.append(M[it.multi_index])
    it.iternext()

我认为附加到列表比R[ctnr]=...更简单,更快捷。如果R是常规数组,并且稀疏索引较慢(甚至是最快的lil格式),那么它就具有竞争力。

ndindex包含了对nditer的使用:

R=[]
for index in np.ndindex(A.shape):
    if A[index]:
        R.append(M[index])

ndenumerate也有效:

R = []
for index,a in np.ndenumerate(A):
   if a:
       R.append(M[index])

但我想知道你是否真的想推进cntr每个it步骤,而不仅仅是True个案例。否则,将result重塑为(N,N)并没有多大意义。但在那种情况下,不是你的问题

M[:N, :N].multiply(A)

M是一个密集阵列:

M[:N, :N]*A

事实上,如果MA都稀疏,那么.data的{​​{1}}属性将与multiply列表相同。< / p>

R