2014-09-04 111 views
7

我的问题是以下,如何在二维numpy数组中找到簇大小?

我有一个2D numpy的阵列用0填充的1,用吸收边界条件(所有外元件是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),并返回此数组的簇大小列表。

所谓“集群”我指的是阵列

数组元素[i] [j]时,如果它的所有邻居都为零分离,并且元件1的分离的基团其邻居是元素:

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

所以前一阵在我们的大小(2,1,2,6,1,1,1)

我试图通过创建两个函数来完成这个任务的7个集群,第一个是递归函数:

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时,它会增加计数器“计数”的值,并将元素的值更改为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

这不行,我不能看到那里的错误是...

我想知道是否也许有一个简单的方法来做到这一点。

回答

7

它似乎是一个渗透问题。 如果您安装了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个成员通过eye-percolation的集群。

0

我相信你的方式几乎是正确的,除非你递归地调用你的函数clust_size一次又一次地初始化变量count。我会将计数变量添加到clust_size的输入参数中,并且只需在嵌套的for循环中为每个第一次呼叫重新初始化它即可,其中count = 0即可。

像这样,你会打电话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 
1

我觉得你的问题找到“群集”,本质上是基于4连接在二进制映像(值为0或1)中查找连接组件的相同问题。你可以看到几种算法在这个维基百科页面识别所连接的组件(或“集群”为您定义他们):

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

一旦连接组件或“集群”的标记,你可以找到任何信息你很容易,包括区域,相对位置或任何其他信息,你可能想要的。

相关问题