2016-05-26 19 views
5

ho un array/set con interi positivi unici, cioèNumpy trovando indice elemento di un'altra matrice

>>> unique = np.unique(np.random.choice(100, 4, replace=False)) 

E un array contenente più elementi del campione da questa matrice precedente, come

>>> A = np.random.choice(unique, 100) 

Voglio mappare i valori dell'array A nella posizione in cui tali valori si verificano in unique.

Quindi la soluzione migliore che ho trovato è attraverso una matrice di mappatura:

>>> table = np.zeros(unique.max()+1, unique.dtype) 
>>> table[unique] = np.arange(unique.size) 

Le assegna sopra a ciascun elemento l'indice nella matrice, e quindi, può essere utilizzato successivamente per mappare A attraverso indicizzazione avanzata:

>>> table[A] 
array([2, 2, 3, 3, 3, 3, 1, 1, 1, 0, 2, 0, 1, 0, 2, 1, 0, 0, 2, 3, 0, 0, 0, 
     0, 3, 3, 2, 1, 0, 0, 0, 2, 1, 0, 3, 0, 1, 3, 0, 1, 2, 3, 3, 3, 3, 1, 
     3, 0, 1, 2, 0, 0, 2, 3, 1, 0, 3, 2, 3, 3, 3, 1, 1, 2, 0, 0, 2, 0, 2, 
     3, 1, 1, 3, 3, 2, 1, 2, 0, 2, 1, 0, 1, 2, 0, 2, 0, 1, 3, 0, 2, 0, 1, 
     3, 2, 2, 1, 3, 0, 3, 3], dtype=int32) 

Quale già mi dà la soluzione corretta. Tuttavia, se i numeri univoci in unique sono molto sparsi e grandi, questo approccio implica la creazione di un array molto grande table solo per memorizzare alcuni numeri per il successivo mapping.

C'è qualche soluzione migliore?

NOTA: sia A e unique sono array di campioni, non array reali. Quindi la domanda non è come generare gli indici di posizione, è solo come mappare in modo efficiente gli elementi di A a indici in unique, il pseudocodice di quello che vorrei per accelerare in NumPy è il seguente,

B = np.zeros_like(A) 
for i in range(A.size): 
    B[i] = unique.index(A[i]) 

(supponendo che unique sia un elenco nello pseudocodice ).

risposta

4

L'approccio tabella descritta nella tua domanda è l'opzione migliore quando unique se abbastanza densa, ma unique.searchsorted(A) dovrebbe produrre lo stesso risultato e non richiede unique a essere denso searchsorted è ottimo con gli ints, se qualcuno sta provando a fare questo genere di cose con i float che hanno limitazioni di precisione, considera qualcosa come this.

+0

E 'possibile usare' sorter', se 'unique' non è già ordinato. – Divakar

1

È possibile utilizzare standard di Python dict con np.vectorize

inds = {e:i for i, e in enumerate(unique)} 
B = np.vectorize(inds.get)(A) 
+0

Un approccio interessante, dovrò testare le prestazioni di 'np.vectorize' per le matrici di grandi dimensioni. –

+0

np.vectorize loop a livello di python, quindi non c'è bisogno di eseguire quel test ... è solo zucchero sintattico –

2

Il pacchetto numpy_indexed (disclaimer: Sono suo autore) contiene un equivalente vettorializzare indice di una lista, che non richiede memoria proporzionale all'elemento massimo, ma solo proporzionale all'ingresso stessa:

import numpy_indexed as npi 
npi.indices(unique, A) 

Nota che funziona anche per dtypes e dimensioni arbitrari. Inoltre, l'array interrogato non deve essere univoco; verrà restituito il primo indice incontrato, lo stesso della lista.