【问题标题】:Extracting multiple submatrices in Python在 Python 中提取多个子矩阵
【发布时间】:2014-11-03 00:14:29
【问题描述】:

如果我的稀疏矩阵有多个非零值区域,我会尝试提取多个子矩阵。

例如, 假设我有以下矩阵:

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() 来查找非零值的索引并仅返回一个子矩阵的区域,但是如何将其扩展到我的稀疏矩阵中的所有可能子区域?

谢谢!

【问题讨论】:

    标签: python indexing


    【解决方案1】:

    程序:

    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
    

    【讨论】:

    • 谢谢,但全局定义出现错误:NameError: global name 'res' is not defined
    • 它似乎也不适用于任何两个子矩阵的一般情况。
    • @alvarezcl,你需要先在主函数中定义res=[]。我已经上传了实际的完整代码。试试看。此外,它适用于两个子矩阵的任何情况。我已经在很多情况下先对其进行了测试。
    【解决方案2】:

    您可以为此使用内置插件。

    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]])
    

    瞧!如果你想取出所有可以迭代的小节,它会告诉你数组中有多少个不同的组。

    【讨论】:

    • 这实际上是比公认的 IMO 更好的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2021-10-14
    • 2020-03-18
    • 1970-01-01
    • 2018-09-23
    • 2013-10-10
    • 1970-01-01
    相关资源
    最近更新 更多