2015-12-12 10 views
5

Mając tablicę 2 x wymiarowej numpy M, chcę policzyć liczbę wystąpień w każdej kolumnie M. Oznacza to, że szukam ogólnej wersji bincount.Zliczanie wystąpień kolumn w tablicy numpy

Co próbowałem do tej pory: (1) Zamienione kolumny na krotki (2) Zakodowane krotki (przez hash) na liczby naturalne (3) użyte numpy.bincount.

Wydaje się to dość niezgrabne. Czy ktoś jest świadomy bardziej eleganckiego i skutecznego sposobu?

+0

ciekawe pytanie. Czekam na wszelkie rozwiązania, ponieważ moja pierwsza i jedyna myśl była dokładnie tym, co zrobiłeś. – Reti43

+0

Więc oczekujesz listy unikatowych kolumn i ich liczników? Czy kolejność kolumn musi zostać zachowana? – imp9

+0

Pokaż kod swoich prób. –

Odpowiedz

4

Można użyć collections.Counter:

>>> import numpy as np 
>>> a = np.array([[ 0, 1, 2, 4, 5, 1, 2, 3], 
...    [ 4, 5, 6, 8, 9, 5, 6, 7], 
...    [ 8, 9, 10, 12, 13, 9, 10, 11]]) 
>>> from collections import Counter 
>>> Counter(map(tuple, a.T)) 
Counter({(2, 6, 10): 2, (1, 5, 9): 2, (4, 8, 12): 1, (5, 9, 13): 1, (3, 7, 11): 
1, (0, 4, 8): 1}) 
1

Dane:

a = np.array([[ 0, 1, 2, 4, 5, 1, 2, 3], 
       [ 4, 5, 6, 8, 9, 5, 6, 7], 
       [ 8, 9, 10, 12, 13, 9, 10, 11]]) 
b = np.transpose(a) 
  1. Bardziej korzystnym rozwiązaniem niż mieszania (nadal wymaga manipulowania)

    utworzyć widok matrycy z elastycznego typu danych np.void (patrz here), takie że każdy rząd staje się pojedynczym elementem. Konwersja do tego kształtu pozwoli na działanie na nim np.unique.

    %%timeit  
    c = np.ascontiguousarray(b).view(np.dtype((np.void, b.dtype.itemsize*b.shape[1]))) 
    _, index, counts = np.unique(c, return_index = True, return_counts = True) 
    #counts are in the last column, remember original array is transposed 
    >>>np.concatenate((b[idx], cnt[:, None]), axis = 1) 
    array([[ 0, 4, 8, 1], 
         [ 1, 5, 9, 2], 
         [ 2, 6, 10, 2], 
         [ 3, 7, 11, 1], 
         [ 4, 8, 12, 1], 
         [ 5, 9, 13, 1]]) 
    10000 loops, best of 3: 65.4 µs per loop 
    

    Liczniki dołączone do unikatowych kolumn a.

  2. Twoje rozwiązanie mieszania.

    %%timeit 
    array_hash = [hash(tuple(row)) for row in b] 
    uniq, index, counts = np.unique(array_hash, return_index= True, return_counts = True) 
    np.concatenate((b[idx], cnt[:, None]), axis = 1) 
    10000 loops, best of 3: 89.5 µs per loop 
    

Aktualizacja: rozwiązanie EPH jest najbardziej wydajny i elegancki.

%%timeit 
Counter(map(tuple, a.T)) 
10000 loops, best of 3: 38.3 µs per loop