2013-02-13 10 views
15

Chcę sprawdzić, czy wszystkie wartości w kolumnach tablicy/macierzy numpy są takie same. Próbowałem użyć reduce z ufuncequal, ale nie wydają się działać we wszystkich przypadkach:Jak sprawdzić, czy wszystkie wartości w kolumnach macierzy numpy są takie same?

In [55]: a = np.array([[1,1,0],[1,-1,0],[1,0,0],[1,1,0]]) 

In [56]: a 
Out[56]: 
array([[ 1, 1, 0], 
     [ 1, -1, 0], 
     [ 1, 0, 0], 
     [ 1, 1, 0]]) 

In [57]: np.equal.reduce(a) 
Out[57]: array([ True, False, True], dtype=bool) 

In [58]: a = np.array([[1,1,0],[1,0,0],[1,0,0],[1,1,0]]) 

In [59]: a 
Out[59]: 
array([[1, 1, 0], 
     [1, 0, 0], 
     [1, 0, 0], 
     [1, 1, 0]]) 

In [60]: np.equal.reduce(a) 
Out[60]: array([ True, True, True], dtype=bool) 

Dlaczego środkowa kolumna w drugim przypadku ocenić również True, podczas gdy powinno być False?

Dzięki za pomoc!

+1

Ten problem przez pewien czas mnie dręczył. Podczas gdy rozwiązanie @ Ubuntu jest wystarczająco eleganckie, nie jest zbyt przyjemne próbować uruchomić to na podwójnej tablicy 4096 ** 3 tylko po to, aby uzyskać tablicę typu boolean, która śledzi dowolną pamięć, którą zostawiłeś. Bawiłem się z czystą implementacją Pythona używając 'np.equal (a, a [:, 0, None])', ale to kończy się z tym samym problemem. W związku z tym pracuję nad PR dla numpy, aby dodać nową funkcję 'np.same' do obsługi dokładnie tego rodzaju sytuacji. –

Odpowiedz

24
In [45]: a 
Out[45]: 
array([[1, 1, 0], 
     [1, 0, 0], 
     [1, 0, 0], 
     [1, 1, 0]]) 

Porównaj każdą wartość do odpowiedniej wartości w pierwszym rzędzie:

In [46]: a == a[0,:] 
Out[46]: 
array([[ True, True, True], 
     [ True, False, True], 
     [ True, False, True], 
     [ True, True, True]], dtype=bool) 

Kolumna dzieli wspólną wartość, jeśli wszystkie wartości w tej kolumnie są prawdziwe:

In [47]: np.all(a == a[0,:], axis = 0) 
Out[47]: array([ True, False, True], dtype=bool) 

Problem z np.equal.reduce można zobaczyć, analizując mikroprocesorowo, co dzieje się po zastosowaniu go do [1, 0, 0, 1]:

In [49]: np.equal.reduce([1, 0, 0, 1]) 
Out[50]: True 

Pierwsze dwie pozycje, 1 i 0 są testowane pod kątem równości, a wynik jest False:

In [51]: np.equal.reduce([False, 0, 1]) 
Out[51]: True 

Teraz False i 0 są testowane pod kątem równości, a wynik jest True:

In [52]: np.equal.reduce([True, 1]) 
Out[52]: True 

Ale True i 1 są równe, więc łączna wynikiem jest True, co nie jest pożądanym rezultatem.

Problem polega na tym, że reduce próbuje zebrać wynik "lokalnie", podczas gdy chcemy "globalnego" testu, takiego jak np.all.

+0

Świetna odpowiedź. Czy istnieje sposób na zrobienie czegoś takiego dla dużych tablic bez tworzenia tablicy maskującej? To musiało być początkowe odwołanie się OP do używania 'zmniejszenia'. –

+1

Nie jestem świadomy żadnej metody NumPy, dzięki której można uzyskać wynik bez tablic tempowych (boolowskich) . Jeśli pracujesz z bardzo dużą tablicą, a pamięć jest ciasna, możesz "porąbać" ją na kawałki (np. Tablice składające się z rzędów N ) i przetestować każdy kawałek osobno. Następnie połącz i przetestuj kawałki, agregując wynik. – unutbu

+1

Możesz także zajrzeć do [numpy.memmap] (http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.memmap.html), lub [Pytables] (http://www.pytables.org/) lub [h5py] (http://www.h5py.org/) dla przechowywania dużej macierzy na dysku, dzięki czemu można wyodrębnić i pracować z jednym kawałkiem z tablicy w czas bez konieczności przechowywania całej tablicy w pamięci. W ten sposób możesz mieć więcej miejsca na tymczasowe tablice NumPy (zwykle) wymaga. – unutbu

7

danym Ubuntu niesamowite wyjaśnienie, można użyć reduce aby rozwiązać problem, ale trzeba zastosować go do bitwise_and i bitwise_or zamiast equal. W konsekwencji, to nie będzie działać z pływającymi tablic punkcie:

In [60]: np.bitwise_and.reduce(a) == a[0] 
Out[60]: array([ True, False, True], dtype=bool) 

In [61]: np.bitwise_and.reduce(b) == b[0] 
Out[61]: array([ True, False, True], dtype=bool) 

zasadzie porównywania bity każdego elementu w kolumnie. Identyczne bity pozostają niezmienione. Różne bity są ustawione na zero. W ten sposób każda liczba, która ma zero zamiast jednego bitu, zmieni zredukowaną wartość. bitwise_and nie będzie pułapką, w przypadku gdy wprowadzone są bity zamiast usunięte:

In [62]: c = np.array([[1,0,0],[1,0,0],[1,0,0],[1,1,0]]) 

In [63]: c 
Out[63]: 
array([[1, 0, 0], 
     [1, 0, 0], 
     [1, 0, 0], 
     [1, 1, 0]]) 

In [64]: np.bitwise_and.reduce(c) == c[0] 
Out[64]: array([ True, True, True], dtype=bool) 

Drugi coumn jest oczywiście błędne.Musimy wykorzystać bitwise_or pułapkę nowych bitów:

In [66]: np.bitwise_or.reduce(c) == c[0] 
Out[66]: array([ True, False, True], dtype=bool) 

ostateczna odpowiedź

In [69]: np.logical_and(np.bitwise_or.reduce(a) == a[0], np.bitwise_and.reduce(a) == a[0]) 
Out[69]: array([ True, False, True], dtype=bool) 

In [70]: np.logical_and(np.bitwise_or.reduce(b) == b[0], np.bitwise_and.reduce(b) == b[0]) 
Out[70]: array([ True, False, True], dtype=boo 

In [71]: np.logical_and(np.bitwise_or.reduce(c) == c[0], np.bitwise_and.reduce(c) == c[0]) 
Out[71]: array([ True, False, True], dtype=bool) 

Metoda ta jest bardziej restrykcyjna i mniej elegancki niż sugestia ubunut za korzystania all, ale ma tę zaletę, że nie tworzenie ogromnych tymczasowych tablic, jeśli twoje wejście jest ogromne. Tymczasowe tablice powinny być tak duże, jak pierwszy rząd macierzy.

EDIT

podstawie tej Q/A i the bug I filed with numpy, rozwiązanie pod warunkiem, działa tylko dlatego, że tablica zawiera zer i jedynek. Tak się składa, że ​​przedstawione operacje bitwise_and.reduce() mogą tylko zwracać zero lub jeden, ponieważ bitwise_and.identity jest niezamierzony, a nie 012486. Utrzymuję tę odpowiedź w nadziei, że numpy zostanie naprawiony, a odpowiedź stanie się prawidłowa.

Edit

Wygląda na to, że będzie w rzeczywistości zmiana NumPy wkrótce. Z pewnością do bitwise_and.identity, a także ewentualnie opcjonalny parametr do zmniejszenia.

Edit

Dobra wiadomość dla wszystkich. Identyfikator dla np.bitwise_and został ustawiony na -1 od wersji 1.12.0.

Powiązane problemy