2015-02-23 13 views
5

Próbowałem zainicjować csc_matrix i csr_matrix z listy wartości (data, (rows, cols)), zgodnie z sugestią dokumentacji.Ignorowanie duplikatów wpisów w rzadkiej macierzy

sparse = csc_matrix((data, (rows, cols)), shape=(n, n)) 

Problemem jest to, że sposób, że rzeczywiście mają do generowania data, rows i cols wektory wprowadza duplikaty dla niektórych punktach. Domyślnie scipy dodaje wartości duplikatów. Jednak w moim przypadku te duplikaty mają dokładnie taką samą wartość w przypadku data dla danego (row, col).

Próbuję osiągnąć to, że scipy zignoruje drugi wpis, jeśli już istnieje, zamiast je dodawać.

Ignorując fakt, że mogłem poprawić algorytm generowania, aby uniknąć generowania duplikatów, czy istnieje parametr lub inny sposób tworzenia rzadkiej macierzy, która ignoruje duplikaty?

Obecnie dwa wpisy z generują rzadką macierz, której wartość pod adresem (1,1) to 8, a pożądaną wartością jest 4.

>>> c = csc_matrix(([4, 4], ([1,1],[1,1])), shape=(3,3)) 
>>> c.todense() 
matrix([[0, 0, 0], 
     [0, 8, 0], 
     [0, 0, 0]]) 

Jestem też świadomy, że mogę filtrować je za pomocą 2-wymiarową numpy unique funkcję, ale listy są dość duży, więc to nie jest tak naprawdę ważne rozwiązaniem.

Inne możliwe odpowiedzi na pytanie: Czy istnieje sposób określenia, co zrobić z duplikatami? tj. zachowując min lub max zamiast domyślnego sum?

+0

Jestem pewien, że odpowiedź brzmi nie, nie ma wbudowanego sposobu zmiany zachowania duplikatów. Nie należy jednak zbyt szybko rezygnować z używania słowa 'np.unique': niezależnie od tego, jak duże są twoje listy, scipy zamieni je na tablice i wykona podobne operacje pod maską, więc nie ma powodu, dla którego nie należy próbować. – Jaime

+1

'np.unique' to 1d, więc obsługa tych współrzędnych 2d będzie wymagać dodatkowego wysiłku. – hpaulj

+1

To prawda, ale takie sztuczki jak [this] (http://stackoverflow.com/questions/16970982/find-unique-rows-in-numpy-array) czynią to 2D. –

Odpowiedz

4

Tworzenie pośrednika dok macierz pracuje w swoim przykładzie:

In [410]: c=sparse.coo_matrix((data, (cols, rows)),shape=(3,3)).todok().tocsc() 

In [411]: c.A 
Out[411]: 
array([[0, 0, 0], 
     [0, 4, 0], 
     [0, 0, 0]], dtype=int32) 

coo matryca stawia swoje tablice wejściowe do jego data, col, row atrybutów bez zmian. Sumowanie nie występuje, dopóki nie zostanie przekonwertowane na csc.

todok ładuje słownik bezpośrednio z atrybutów coo. Tworzy pusty dok matrycę, a wypełnia go:

dok.update(izip(izip(self.row,self.col),self.data)) 

Więc jeśli istnieje duplikat (row,col) wartości, to ten ostatni, który pozostaje. Używa standardowego hashowania w słowniku Python, aby znaleźć unikalne klucze.


Oto sposób korzystania z np.unique. Musiałem zbudować specjalną tablicę obiektów, ponieważ unique działa na 1d, a my mamy indeksowanie 2d.

In [479]: data, cols, rows = [np.array(j) for j in [[1,4,2,4,1],[0,1,1,1,2],[0,1,2,1,1]]] 

In [480]: x=np.zeros(cols.shape,dtype=object) 

In [481]: x[:]=list(zip(rows,cols)) 

In [482]: x 
Out[482]: array([(0, 0), (1, 1), (2, 1), (1, 1), (1, 2)], dtype=object) 

In [483]: i=np.unique(x,return_index=True)[1] 

In [484]: i 
Out[484]: array([0, 1, 4, 2], dtype=int32) 

In [485]: c1=sparse.csc_matrix((data[i],(cols[i],rows[i])),shape=(3,3)) 

In [486]: c1.A 
Out[486]: 
array([[1, 0, 0], 
     [0, 4, 2], 
     [0, 1, 0]], dtype=int32) 

Nie mam pojęcia, które podejście jest szybsze.


Alternatywnym sposobem na uzyskanie unikalnego indeksu, zgodnie liuengo's linku:

rc = np.vstack([rows,cols]).T.copy() 
dt = rc.dtype.descr * 2 
i = np.unique(rc.view(dt), return_index=True)[1] 

rc ma posiadać własne dane w celu zmiany dtype z widzenia, stąd .T.copy().

In [554]: rc.view(dt) 
Out[554]: 
array([[(0, 0)], 
     [(1, 1)], 
     [(2, 1)], 
     [(1, 1)], 
     [(1, 2)]], 
     dtype=[('f0', '<i4'), ('f1', '<i4')]) 
+0

Wygląda miłą sztuczkę. Nie mogę tego teraz wypróbować, czy konwersja między typami zajmuje dużo czasu/pamięci? –

+0

todok() nie ignoruje duplikatów na scipy 0.19 –

+0

Tak, 'coo.todok' zawiera teraz linię' self.sum_duplicates() '. Rozwiązaniem jest aktualizacja, tak jak opisuję, ale bez tej "sumy". – hpaulj

Powiązane problemy