2013-04-11 15 views
18

Ten problem wydaje się łatwy, ale nie mogę znaleźć ładnie wyglądającego rozwiązania. Mam dwie niezgrabne tablice (A i B) i chcę uzyskać indeksy A, w których elementy A są w B, a także uzyskać indeksy A, w których elementy nie są w B.Sprawdź, czy każdy element w tablicy numpy znajduje się w innej tablicy.

Tak więc, jeśli

A = np.array([1,2,3,4,5,6,7]) 
B = np.array([2,4,6]) 

Obecnie używam

C = np.searchsorted(A,B) 

który wykorzystuje fakt, że A jest w porządku, i daje mi [1, 3, 5] indeksy z elementów, które znajdują się w A. To świetnie, ale jak uzyskać D = [0,2,4,6], indeksy elementów A, które nie są w B?

Odpowiedz

6
import numpy as np 

A = np.array([1,2,3,4,5,6,7]) 
B = np.array([2,4,6]) 
C = np.searchsorted(A, B) 

D = np.delete(np.arange(np.alen(A)), C) 

D 
#array([0, 2, 4, 6]) 
+0

Dzięki! Podoba mi się również odpowiedź udzielona przez alexhb przy użyciu np.setdiff1d. Miałem nadzieję, że istnieje funkcja, która dałaby mi wskaźniki bezpośrednio, ale działa to dobrze. – DanHickstein

+0

Może być, @ Dan, ale nie mogę o tym myśleć. Jeśli nie potrzebujesz 'C', użyj jego rozwiązania, ale moje będzie dwa razy szybsze, jeśli masz już' C'. – askewchan

3
import numpy as np 

a = np.array([1, 2, 3, 4, 5, 6, 7]) 
b = np.array([2, 4, 6]) 
c = np.searchsorted(a, b) 
d = np.searchsorted(a, np.setdiff1d(a, b)) 

d 
#array([0, 2, 4, 6]) 
+0

Poszukiwanie dwa razy spowalnia to nieco, lepiej użyć już znanego 'C', aby uzyskać' D'. Ale jest to oczywiście lepsze rozwiązanie, jeśli 'C' nie jest potrzebny, więc +1. (Witamy w [SO]!) – askewchan

30

searchsorted może dać błędną odpowiedź, jeśli nie każdy element B jest A. Można użyć numpy.in1d:

A = np.array([1,2,3,4,5,6,7]) 
B = np.array([2,4,6,8]) 
mask = np.in1d(A, B) 
print np.where(mask)[0] 
print np.where(~mask)[0] 

wyjście jest:

[1 3 5] 
[0 2 4 6] 

Jednak in1d() używa sortowania, które jest powolne w przypadku dużych zbiorów danych. Można użyć pandy, czy zbiór danych jest duża:

import pandas as pd 
np.where(pd.Index(pd.unique(B)).get_indexer(A) >= 0)[0] 

Oto porównanie czas:

A = np.random.randint(0, 1000, 10000) 
B = np.random.randint(0, 1000, 10000) 

%timeit np.where(np.in1d(A, B))[0] 
%timeit np.where(pd.Index(pd.unique(B)).get_indexer(A) >= 0)[0] 

wyjściowa:

100 loops, best of 3: 2.09 ms per loop 
1000 loops, best of 3: 594 µs per loop 
+2

Dobrze jest wiedzieć o tej skutecznej metodzie, ponieważ moje zbiory danych są bardzo duże. Wielkie dzięki za to rozwiązanie! – DanHickstein

2

z elementów, które są również w B:

zestaw (A) & zestaw (B)

z elementów, które nie są w B:

zestaw (A) - zestaw (B)

Powiązane problemy