2014-09-04 11 views
7

Mein Problem ist die folgende,Wie Clustergrößen in 2D-numpy-Array zu finden?

Ich habe ein mit 0 ein 1, mit einer absorbierenden Randbedingung (all äußeren Elemente sind 0), beispielsweise gefüllt numpy Array 2D:

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

Ich mag um eine Funktion zu erstellen, die dieses Array und seine lineare Dimension L als Eingabeparameter verwendet (in diesem Fall L = 10) und die Liste der Clustergrößen dieses Arrays zurückgibt.

von „Clustern“ meine ich die isolierten Gruppen von Elementen 1 des Arrays

dem Array-Element [i] [j] isoliert wird, wenn alle seine Nachbarn Nullen sind, und ihre Nachbarn sind die Elemente:

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

So in der vorherigen Anordnung haben wir 7 Cluster von Größen (2,1,2,6,1,1,1)

ich habe versucht, diese Aufgabe abzuschließen durch zwei Funktionen erstellen, die erste ist eine rekursive Funktion:

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   

und es sollte die Größe eines Clusters zurückgeben. Jedes Mal, wenn die Funktion ein Array-Element gleich 1 findet, erhöht sie den Wert des Zählers "count" und ändert den Wert des Elements in 0, auf diese Weise wird jedes "1" -Element nur einmal gezählt. Wenn einer der Nachbarn des Elements gleich 1 ist, ruft die Funktion sich selbst für dieses Element auf.

Die zweite Funktion ist:

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 

und es sollte die Liste mit den Clustergrößen zurück. Die for-Schleife iteriert von 1 bis L-1, da alle äußeren Elemente sind 0.

Dies funktioniert nicht, und ich kann nicht sehen, wo der Fehler ...

Ich frage mich, vielleicht, wenn es ein einfacher Weg, es zu tun.

Antwort

7

es wie ein Versickerungs Problem scheint. Der folgende Link hat Ihre Antwort, wenn Sie scipy installiert haben.

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

Dadurch werden die Cluster identifizieren:

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

Die folgende ihrem Gebiet berechnen wird.

Dies gibt, was Sie erwarten, obwohl ich denken würde, dass Sie einen Cluster mit 8 Mitgliedern per Augenperkolation hätten.

0

Ich glaube, dass Ihr Weg fast richtig ist, nur dass Sie die Variable count immer wieder initialisieren, wenn Sie Ihre Funktion clust_size rekursiv aufrufen. Ich würde die Zählvariable zu den Eingabeparametern von clust_size hinzufügen und es für jeden ersten Anruf in Ihren verschachtelten for-Schleifen mit count = 0 einfach reinitialisieren.

So würden Sie rufen clust_size immer wie count=clust_size(array, i ,j, count) Ich habe es nicht getestet, aber es scheint mir, dass es funktionieren sollte.

Ich hoffe, es hilft.

-2

Ein relativ einfaches Problem, wenn Sie wandeln diese in Strings

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

Ausgang

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

Ich fühle Ihr Problem mit der Suche nach "Clustern", ist im Wesentlichen das gleiche Problem der Suche nach verbundenen Komponenten in einem binären Bild (mit Werten von entweder 0 oder 1) basierend auf 4-Konnektivität. Sie können mehrere Algorithmen sehen die angeschlossenen Komponenten (oder „Cluster“, wie Sie sie definiert sind) zu identifizieren, in dieser Wikipedia-Seite:

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

Sobald die angeschlossenen Komponenten oder „Cluster“ gekennzeichnet sind, können Sie alle Informationen finden Sie wollen leicht, einschließlich der Fläche, relative Position oder andere Informationen, die Sie wollen.