如何在 2D numpy 数组中查找簇大小?

Posted

技术标签:

【中文标题】如何在 2D numpy 数组中查找簇大小?【英文标题】:How to find cluster sizes in 2D numpy array? 【发布时间】:2014-10-29 03:44:46 【问题描述】:

我的问题如下,

我有一个用 0 和 1 填充的 2D numpy 数组,具有吸收边界条件(所有外部元素都是 0),例如:

[[0 0 0 0 0 0 0 0 0 0]
 [0 0 1 0 0 0 0 0 0 0]
 [0 0 1 0 1 0 0 0 1 0]
 [0 0 0 0 0 0 1 0 1 0]
 [0 0 0 0 0 0 1 0 0 0]
 [0 0 0 0 1 0 1 0 0 0]
 [0 0 0 0 0 1 1 0 0 0]
 [0 0 0 1 0 1 0 0 0 0]
 [0 0 0 0 1 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]]

我想创建一个函数,将该数组及其线性维度 L 作为输入参数(在本例中 L = 10)并返回该数组的簇大小列表。

“簇”是指数组中元素 1 的孤立组

如果它的所有邻居都为零,则数组元素 [ i ][ j ] 是孤立的,并且它的邻居是元素:

[i+1][j]
[i-1][j]
[i][j+1]
[i][j-1]

所以在前面的数组中,我们有 7 个大小为 (2,1,2,6,1,1,1) 的簇

我尝试通过创建两个函数来完成这个任务,第一个是递归函数:

def clust_size(array,i,j):

    count = 0

    if array[i][j] == 1:

        array[i][j] = 0

        if array[i-1][j] == 1:

            count += 1
            array[i-1][j] = 0
            clust_size(array,i-1,j)

        elif array[i][j-1] == 1:

            count += 1
            array[i-1][j] = 0
            clust_size(array,i,j-1)

        elif array[i+1][j] == 1:

            count += 1
            array[i-1][j] =  0
            clust_size(array,i+1,j)

        elif array[i][j+1] == 1:

            count += 1
            array[i-1][j] = 0
            clust_size(array,i,j+1)

    return count+1         

它应该返回一个簇的大小。每次函数找到一个等于 1 的数组元素时,它都会增加计数器“count”的值并将元素的值更改为 0,这样每个“1”元素只计算一次。 如果元素的相邻元素之一等于 1,则函数在该元素上调用自身。

第二个功能是:

def clust_list(array,L):

    sizes_list = []

    for i in range(1,L-1):
        for i in range(1,L-1):

           count = clust_size(array,i,j)

           sizes_list.append(count)

    return sizes_list

它应该返回包含集群大小的列表。 for 循环从 1 迭代到 L-1,因为所有外部元素都是 0。

这不起作用,我看不到错误在哪里......

我想知道是否有更简单的方法。

【问题讨论】:

【参考方案1】:

我相信你的方法几乎是正确的,除了你在递归调用你的函数clust_size 时一遍又一遍地初始化变量count。我会将 count 变量添加到 clust_size 的输入参数中,并在使用 count = 0 嵌套的 for 循环中的每次第一次调用时重新初始化它。

像这样,你会打电话给clust_size 总是像count=clust_size(array, i ,j, count) 我还没有测试过,但在我看来它应该可以工作。

希望对你有帮助。

【讨论】:

【参考方案2】:

如果将其转换为字符串,这是一个相对简单的问题

import numpy as np                                       
arr=np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0,],           
              [0, 0, 1, 0, 0, 0, 0, 0, 0, 0,],           
              [0, 0, 1, 1, 1, 1, 1, 1, 1, 0,],   #modified        
              [0, 0, 0, 0, 0, 0, 1, 0, 1, 0,],           
              [0, 0, 0, 0, 0, 0, 1, 0, 0, 0,],           
              [0, 0, 0, 0, 1, 0, 1, 0, 0, 0,],           
              [0, 0, 0, 0, 0, 1, 1, 0, 0, 0,],           
              [0, 0, 0, 1, 0, 1, 0, 0, 0, 0,],           
              [0, 0, 0, 0, 1, 0, 0, 0, 0, 0,],           
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])           

arr = "".join([str(x) for x in arr.reshape(-1)])         
print [len(x) for x in arr.replace("0"," ").split()] 

输出

[1, 7, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1] #Cluster sizes

【讨论】:

【参考方案3】:

这似乎是一个渗透问题。 如果您安装了 scipy,则以下链接有您的答案。

http://dragly.org/2013/03/25/working-with-percolation-clusters-in-python/

from pylab import *
from scipy.ndimage import measurements

z2 = array([[0,0,0,0,0,0,0,0,0,0],
    [0,0,1,0,0,0,0,0,0,0],
    [0,0,1,0,1,0,0,0,1,0],
    [0,0,0,0,0,0,1,0,1,0],
    [0,0,0,0,0,0,1,0,0,0],
    [0,0,0,0,1,0,1,0,0,0],
    [0,0,0,0,0,1,1,0,0,0],
    [0,0,0,1,0,1,0,0,0,0],
    [0,0,0,0,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0]])

这将识别集群:

lw, num = measurements.label(z2)
print lw
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
   [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
   [0, 0, 1, 0, 2, 0, 0, 0, 3, 0],
   [0, 0, 0, 0, 0, 0, 4, 0, 3, 0],
   [0, 0, 0, 0, 0, 0, 4, 0, 0, 0],
   [0, 0, 0, 0, 5, 0, 4, 0, 0, 0],
   [0, 0, 0, 0, 0, 4, 4, 0, 0, 0],
   [0, 0, 0, 6, 0, 4, 0, 0, 0, 0],
   [0, 0, 0, 0, 7, 0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

下面将计算它们的面积。

area = measurements.sum(z2, lw, index=arange(lw.max() + 1))
print area
[ 0.  2.  1.  2.  6.  1.  1.  1.]

这给出了您所期望的,尽管我认为您将拥有一个包含 8 个成员的集群。

【讨论】:

【参考方案4】:

我觉得您在查找“集群”时遇到的问题,本质上与在基于 4 连通性的二进制图像(值为 0 或 1)中查找连通分量的问题相同。您可以在此 Wikipedia 页面中看到几种算法来识别连接的组件(或您定义的“集群”):

http://en.wikipedia.org/wiki/Connected-component_labeling

标记连接的组件或“集群”后,您可以轻松找到所需的任何信息,包括区域、相对位置或您可能想要的任何其他信息。

【讨论】:

以上是关于如何在 2D numpy 数组中查找簇大小?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 numpy 数组上定义一个使用数组索引查找字典的函数?

如何在 NumPy 中将 HDF5 2D 数组转换为 1D?

通过平均或重新组合一个 numpy 2d 数组来调整大小

如何从 2D numpy (lat,lon) 数组中删除扇区/切片?

如何将 2D float numpy 数组转换为 2D int numpy 数组?

如何将 1d numpy 数组附加到 2d numpy 数组 python