2013-09-01 14 views
5

Genauer gesagt, ich habe eine Liste von Zeilen/Spalten, die ignoriert werden müssen, wenn Sie den maximalen Eintrag auswählen. Mit anderen Worten, wenn der obere obere dreieckige Eintrag ausgewählt wird, müssen bestimmte Indizes übersprungen werden. Was ist in diesem Fall die effizienteste Methode, um den Ort des oberen oberen dreieckigen Eintrags zu finden?Effizienter Weg, um den Index des oberen oberen dreieckigen Eintrags in einem numpligen Array zu finden?

Zum Beispiel:

>>> a 
array([[0, 1, 1, 1], 
     [1, 2, 3, 4], 
     [4, 5, 6, 6], 
     [4, 5, 6, 7]]) 
>>> indices_to_skip = [0,1,2] 

Ich brauche a[0,1] den Index des min Elements unter allen Elementen im oberen Dreieck mit Ausnahme der Einträge zu finden, a[0,2] und a[1,2].

+0

Können Sie eine geben Beispiel? – nneonneo

+0

Gerade die Frage bearbeitet. Vielen Dank! – methane

+0

Also, in dem Beispiel nehmen Sie das Maximum von nur [1,4,6]? Haben Sie die Diagonale oder nicht? – nneonneo

Antwort

5

können Sie np.triu_indices_from verwenden:

>>> np.vstack(np.triu_indices_from(a,k=1)).T 
array([[0, 1], 
     [0, 2], 
     [0, 3], 
     [1, 2], 
     [1, 3], 
     [2, 3]]) 

>>> inds=inds[inds[:,1]>2] #Or whatever columns you want to start from. 
>>> inds 
array([[0, 3], 
     [1, 3], 
     [2, 3]]) 


>>> a[inds[:,0],inds[:,1]] 
array([1, 4, 6]) 

>>> max_index = np.argmax(a[inds[:,0],inds[:,1]]) 
>>> inds[max_index] 
array([2, 3]]) 

Oder:

>>> inds=np.triu_indices_from(a,k=1) 
>>> mask = (inds[1]>2) #Again change 2 for whatever columns you want to start at. 
>>> a[inds][mask] 
array([1, 4, 6]) 

>>> max_index = np.argmax(a[inds][mask]) 
>>> inds[mask][max_index] 
array([2, 3]]) 

Für die oben Sie können inds[0] verwenden Certains Zeilen zu überspringen.

bestimmte Zeilen oder Spalten überspringen:

def ignore_upper(arr, k=0, skip_rows=None, skip_cols=None): 
    rows, cols = np.triu_indices_from(arr, k=k) 

    if skip_rows != None: 
     row_mask = ~np.in1d(rows, skip_rows) 
     rows = rows[row_mask] 
     cols = cols[row_mask] 

    if skip_cols != None: 
     col_mask = ~np.in1d(cols, skip_cols) 
     rows = rows[col_mask] 
     cols = cols[col_mask] 

    inds=np.ravel_multi_index((rows,cols),arr.shape) 
    return np.take(arr,inds) 

print ignore_upper(a, skip_rows=1, skip_cols=2) #Will also take numpy arrays for skipping. 
[0 1 1 6 7] 

Die beiden kombinierten und helfen bestimmten Fällen beschleunigen können kreative Verwendung von boolean Indizierung werden kann.

Etwas interessant, dass ich über lief, ein schnellerer Weg obere triu Indizes zu nehmen:

def fast_triu_indices(dim,k=0): 

    tmp_range = np.arange(dim-k) 
    rows = np.repeat(tmp_range,(tmp_range+1)[::-1]) 

    cols = np.ones(rows.shape[0],dtype=np.int) 
    inds = np.cumsum(tmp_range[1:][::-1]+1) 

    np.put(cols,inds,np.arange(dim*-1+2+k,1)) 
    cols[0] = k 
    np.cumsum(cols,out=cols) 
    return (rows,cols) 

Es geht um ~ 6x schneller, obwohl es nicht für k<0 funktioniert:

dim=5000 
a=np.random.rand(dim,dim) 

k=50 
t=time.time() 
rows,cols=np.triu_indices(dim,k=k) 
print time.time()-t 
0.913508892059 

t=time.time() 
rows2,cols2,=fast_triu_indices(dim,k=k) 
print time.time()-t 
0.16515994072 

print np.allclose(rows,rows2) 
True 

print np.allclose(cols,cols2) 
True 
+0

Das sieht gut aus, aber was ist mit dem Index des Max-Elements, nicht nur mit dem Max-Element selbst? – methane

+0

@methane Ich aktualisierte die ersten beiden Beispiele. Sie sollten es von dort aus nehmen können. – Daniel

Verwandte Themen