删除2d numpy数组中0的方形子矩阵

时间:2017-01-25 14:11:19

标签: python numpy

假设我有一个正方形的二维数组,它是一个块对角矩阵大小(N,N)。每个块是(例如)(N_b,N_b)。这些块中的一些仅为0(例如,零的(N_b,N_b)矩阵)。我想挤压这些块留下一个没有(N_b,N_b)0数组的矩阵。

另外,我还想采取其中一种"挤压"矩阵并将其扩展为原始大小(零填充),要求所有元素都在同一个地方

我能想到的一切都需要循环和大量会计。我很乐意使用稀疏矩阵,但这似乎使事情更加复杂。

问题的第一部分("挤压")可以通过这种方式完成:

import numpy as np
import scipy.sparse as sp


A = np.random.randn(3,3)*5
B = A*0.

M = np.array(sp.block_diag ( (A, B, A, A, A, B, A) ).todense())


n_b = A.shape[0]
n_blocks = M.shape[0]/n_b

block_locs = []
nonzero_blocks = []
for this_block in xrange ( n_blocks ):
    if np.all(M[n_b*this_block:(this_block+1)*n_b, n_b*this_block:(this_block+1)*n_b] != 0):
        nonzero_blocks.append (M[n_b*this_block:(this_block+1)*n_b, n_b*this_block:(this_block+1)*n_b] )
        block_locs.append ( this_block )
squeezed_M = sp.block_diag ( nonzero_blocks ).tolil()


blocky = []
this_squeeze_block = 0
for this_block in xrange(n_blocks):
    if this_block in block_locs:
        blocky.append ( squeezed_M[this_squeeze_block*n_b:(this_squeeze_block+1)*n_b,
            this_squeeze_block * n_b:(this_squeeze_block + 1) * n_b])
        this_squeeze_block += 1
    else:
        blocky.append ( np.zeros((n_b, n_b)))
A_big = sp.block_diag(blocky).todense()

print np.allclose(M, A_big)

这里是原始矩阵(零块,顶部)和挤压版本(底部)的图:

编辑利用问题对称性的更简洁方法可能是:

import numpy as np
import scipy.sparse as sp
import matplotlib.pyplot as plt

# First create a big matrix with gaps
n_b = 3
A = np.random.randn(n_b,n_b)*5
B = A*0.
M = sp.block_diag ( (A, B, A, A, A, B, A) )

# Select the rows which are not all zeros
no_zeros = np.any(np.array((M != 0).todense()), axis=1)
n_blocks = no_zeros.sum() 
# where's the meat?
meat = np.outer ( no_zeros, no_zeros )
# We need to use a lil matrix to address by a boolean array
# And then we just reshape
A_squeeze = M.tolil()[meat].reshape((n_blocks, n_blocks))

reco = sp.lil_matrix ( M.shape)
reco[np.outer(no_zeros, no_zeros)]=A_squeeze.todense().ravel()

np.allclose(M.todense(), reco.todense())
plt.subplot(1,2,1)
plt.spy(M)
plt.subplot(1,2,2)
plt.spy(A_squeeze)

1 个答案:

答案 0 :(得分:0)

您可以使用查找等于零的对角元素,然后创建一个2D布尔掩码来选择您的数组。

tf.split_v(tf.shuffle(images, ...), ...)

了解掩码如何消除不需要的行和列?但是,因为numpy不允许锯齿状数组,所以我们必须将import numpy as np a = [[1,1,0,0,0,0,0], [1,1,0,0,0,0,0], [0,0,0,0,0,0,0], [0,0,0,0,0,0,0], [0,0,0,0,2,2,2], [0,0,0,0,2,2,2], [0,0,0,0,2,2,2]] # find the diagonal elements not equal to zero b = np.diag(a) != 0 # create a boolean 2d mask mask = b[np.newaxis] * np.transpose(b[np.newaxis]) > mask # this is the mask output # array([[ True, True, False, False, True, True, True], # [ True, True, False, False, True, True, True], # [False, False, False, False, False, False, False], # [False, False, False, False, False, False, False], # [ True, True, False, False, True, True, True], # [ True, True, False, False, True, True, True], # [ True, True, False, False, True, True, True]], dtype=bool) a重新整形为1D数组,使用布尔索引,然后重新整形回到正方形。

mask
相关问题