2014-09-04 14 views
7

mio problema è il seguente,Come trovare le dimensioni dei cluster in serie numpy 2D?

Ho una matrice NumPy 2D riempito con 0 un 1, con una condizione al contorno assorbente (tutti gli elementi esterni sono 0), ad esempio:

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

voglio per creare una funzione che prende questo array e la sua dimensione lineare L come parametri di input, (in questo caso L = 10) e restituisce l'elenco delle dimensioni del cluster di questo array.

per "cluster" intendo i gruppi isolati di elementi 1 della matrice

dell'elemento array [i] [j] è isolato se tutti i suoi vicini sono zeri, ei suoi vicini sono gli elementi:

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

Così nell'array precedente abbiamo 7 cluster di dimensioni (2,1,2,6,1,1,1)

ho provato a completare questo compito creando due funzioni, il primo è una funzione ricorsiva:

e dovrebbe restituire la dimensione di un cluster. Ogni volta che la funzione trova un elemento dell'array uguale a 1 aumenta il valore del contatore "count" e cambia il valore dell'elemento a 0, in questo modo ogni elemento "1" viene contato una sola volta. Se uno dei vicini dell'elemento è uguale a 1, la funzione si chiama su quell'elemento.

La seconda funzione è:

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 

e deve restituire l'elenco contenente le dimensioni di cluster. Il ciclo for itera da 1 a L-1, perché tutti gli elementi esterni sono 0.

questo non funziona e non riesco a vedere dove l'errore è ...

Mi chiedevo se forse c'è un modo più semplice per farlo.

risposta

7

sembra un problema di percolazione. Il seguente link ha la tua risposta se hai installato 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]]) 

Ciò consentirà di individuare i cluster:

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

Di seguito calcolerà la loro area.

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

Questo dà quello che ci si aspetta, anche se vorrei pensare che si avrebbe un cluster con 8 membri di eye-percolazione.

0

Credo che il tuo modo sia quasi corretto, eccetto che stai inizializzando la variabile count più e più volte quando ricorsivamente chiami la tua funzione clust_size. Aggiungerei la variabile count ai parametri di input di clust_size e semplicemente reinizializzalo per ogni prima chiamata nei tuoi loop nidificati for con count = 0.

In questo modo, si potrebbe chiamare clust_size sempre come count=clust_size(array, i ,j, count) non ho ancora testato, ma a me sembra che dovrebbe funzionare.

Spero che aiuti.

-2

Un relativamente semplice problema se si convertire questo in stringhe

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

uscita

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

Sento che il tuo problema con la ricerca di "cluster", è essenzialmente lo stesso problema di trovare i componenti connessi in un'immagine binaria (con valori di 0 o 1) in base alla connettività a 4. Potete vedere diversi algoritmi per identificare i componenti collegati (o "cluster" come li definite) in questa pagina di Wikipedia:

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

Una volta che i componenti collegati o "cluster" sono etichettati, è possibile trovare tutte le informazioni vuoi facilmente, inclusa l'area, la posizione relativa o qualsiasi altra informazione tu voglia.