2016-05-26 20 views
5

mam tablica/ustaw z unikalnymi dodatnie liczby całkowite, tjNumpy znalezienie indeks elementu w innej tablicy

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

i tablica zawierająca wiele elementów pochodzących od tej poprzedniej tablicy, jak

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

Chcę odwzorować wartości tablicy A na pozycję, której te wartości występują w unique.

Dotychczas najlepszym rozwiązaniem znalazłem jest za pośrednictwem tablicy odwzorowania:

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

Powyższe przypisuje każdego elementu indeks na tablicy, a zatem mogą być wykorzystane później do map A dzięki zaawansowanej indeksowania:

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

Co już daje mi odpowiednie rozwiązanie. Jeśli jednak unikalne liczby w unique są bardzo rzadkie i duże, to podejście zakłada utworzenie bardzo dużej tablicy table tylko po to, aby zapisać kilka liczb do późniejszego odwzorowania.

Czy istnieje lepsze rozwiązanie?

UWAGA: zarówno A, jak i unique są macierzami próbek, , a nie rzeczywistych tablic. Więc nie chodzi o to, jak generować indeksy pozycyjnych, to tylko jak skutecznie map elementy A do indeksów w unique, z Pseudokod co chciałbym przyspieszenie w numpy jest następująca,

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

(przy założeniu, że unique jest listą w powyższym kodzie pseudokod).

Odpowiedz

4

Podejście stołowego opisanego w pytaniu jest najlepszym rozwiązaniem, gdy unique jeśli dość gęsty, ale unique.searchsorted(A) powinna produkować ten sam wynik i nie wymaga unique do być gęsty. searchsorted jest świetny z ints, jeśli ktokolwiek próbuje robić tego rodzaju rzeczy za pomocą pływaków, które mają ograniczenia precyzji, rozważ coś w rodzaju this.

+0

I "sorter" może być używany z nim, jeśli 'unikalny' nie jest już posortowane. – Divakar

1

Można użyć standardowej Pythona dict z np.vectorize

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

Mimo to, będę musiał przetestować wydajność 'np.vectorize' dla dużych macierzy. –

+0

np.vectorize pętle na poziomie python, więc nie trzeba wykonywać tego testu ... jego tylko cukier syntaktyczny –

2

Pakiet numpy_indexed (disclaimer: Jestem jego autorem) zawiera vectorized równowartość list.index, które nie wymagają pamięci proporcjonalny do max elementu, ale tylko proporcjonalnie do wejścia sama:

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

Zauważ, że działa również dla dowolnych dtypów i wymiarów. Również pytana tablica nie musi być unikalna; pierwszy napotkany indeks zostanie zwrócony, taki sam jak dla listy.