2014-11-03 77 views
10

我想提取多个子矩阵,如果我的稀疏矩阵具有非零值的多个区域。在Python中提取多个子矩阵

例如, 说我有下面的矩阵:

x = np.array([0,0,0,0,0,0], 
      [0,1,1,0,0,0], 
      [0,1,1,0,0,1], 
      [0,0,0,0,1,1], 
      [0,0,0,0,1,0]) 

然后我需要能够具有非零值来提取的区域,即

x_1 = [[1,1] 
     [1,1]] 

x_2 = [[0,1], 
     [1,1], 
     [1,0]] 

我一直在使用np.where()来查找非零值和returni的索引这个区域只有一个子矩阵,但是我怎样才能将它扩展到我的稀疏矩阵中所有可能的子区域?

谢谢!

回答

7

步骤:

  1. 删除开头和结尾的行和列的都是零。 (不是中间的)
  2. 在这些索引上查找所有空行和列以及拆分矩阵。这将创建矩阵
  3. 对于每个新创建的矩阵重复这个过程递归的列表,直到没有进一步的分裂可能

代码:

def delrc(arr): 
    while True:  # delete leading rows with all zeros 
    if np.all(arr[0]==0): 
     arr=np.delete(arr,0,axis=0) 
    else: break 
    while True:  # delete trailing rows with all zeros 
    if np.all(arr[-1]==0): 
     arr=np.delete(arr,-1,axis=0) 
    else: break 
    while True:  # delete leading cols with all zeros 
    if np.all(arr[:,0]==0): 
     arr=np.delete(arr,0,axis=1) 
    else: break 
    while True:  # delete trailing cols with all zeros 
    if np.all(arr[:,-1]==0): 
     arr=np.delete(arr,-1,axis=1) 
    else: break 
    return arr 

def rcsplit(arr): 
    if np.all(arr==0): return [] # if all zeros return 
    global res 
    arr = delrc(arr)  # delete leading/trailing rows/cols with all zeros 
    print arr 
    indr = np.where(np.all(arr==0,axis=1))[0] 
    indc = np.where(np.all(arr==0,axis=0))[0] 
    if not indr and not indc: # If no further split possible return 
    res.append(arr) 
    return 
    arr=np.delete(arr,indr,axis=0) #delete empty rows in between non empty rows 
    arr=np.delete(arr,indc,axis=1) #delete empty cols in between non empty cols 
    arr=np.split(arr,indc,axis=1) # split on empty (all zeros) cols 
    print arr 
    arr2=[] 
    for i in arr: 
    z=delrc(i) 
    arr2.extend(np.split(z,indr,axis=0)) # split on empty (all zeros) rows 
    for i in arr2: 
    rcsplit(np.array(i))  # recursive split again no further splitting is possible 

if __name__=="__main__": 

    import numpy as np 
    res = [] 
    arr = np.array([[0,0,0,0,0,0], 
     [0,1,1,0,0,0], 
     [0,1,1,0,0,1], 
     [0,0,0,0,1,1], 
     [0,0,0,0,1,0]]) 
    rcsplit(arr) 
    for i in res: print i 
+0

谢谢你,但我得到一个错误与全局定义: NameError:全局名称“水库”没有定义 – alvarezcl 2014-11-30 20:16:26

+0

这也似乎并不奏效任何两个子矩阵的一般情况。 – alvarezcl 2014-11-30 21:13:46

+0

@alvarezcl,你需要首先在主函数中定义'res = []'。我已经上传了实际的完整代码。尝试一下。此外,它适用于任何两个子矩阵的情况。我已经在很多情况下首先进行了测试。 – 2014-12-01 04:30:37

3

您可以使用内置插件此。

from scipy.ndimage.measurements import find_objects, label 
from scipy.ndimage import generate_binary_structure as gbs 

import numpy as np 

# create array 
x = np.array([[0,0,0,0,0,0], 
      [0,1,1,0,0,0], 
      [0,1,1,0,0,1], 
      [0,0,0,0,1,1], 
      [0,0,0,0,1,0]]) 

# define labeling structure to inlcude adjacent (including diagonal) cells 
struc = gbs(2,2) 

# generate array of labeled sections labels 
x2, numlabels = label(x,struc) 

# pull out first group of "ones" 
xy1 = find_objects(x2==1)[0] 

# pull out second group of "ones" 
xy2 = find_objects(x2==2)[0] 

现在测试:

>>> x[xy1] 
    array([[1, 1], 
      [1, 1]]) 

>>> x[xy2] 
    array([[0, 1], 
      [1, 1], 
      [1, 0]]) 

瞧!如果您想要拉出所有可以迭代的小节,这会告诉您阵列中有多少个不同的小组。

+0

这实际上比接受的IMO更好的解决方案。 – 2014-12-24 12:38:27