2014-11-03 68 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