2015-06-09 31 views
12

scipy.sparse.coo_matrix.max zwraca maksymalną wartość każdego wiersza lub kolumny, z uwzględnieniem osi. Chciałbym poznać nie wartość, ale indeks maksymalnej wartości każdego wiersza lub kolumny. Nie znalazłem jeszcze sposobu, aby zrobić to w skuteczny sposób, więc chętnie przyjmuję jakąkolwiek pomoc.Argmax każdego wiersza lub kolumny w rzadkiej matrycy scipy

+0

Możesz spróbować tego: http://stackoverflow.com/a/9337071/1738214 przetwarza każdy wiersz osobno – gcucurull

Odpowiedz

2

Od wersji scipy 0.19, zarówno csr_matrix, jak i csc_matrix, obsługujących metody argmax() i argmin().

1

Jeśli A to scipy.sparse.coo_matrix, a następnie pojawi się wiersz i kolumnę o maksymalnej wartości w następujący sposób:

I=A.data.argmax() 
maxrow = A.row[I] 
maxcol=A.col[I] 

Aby uzyskać indeks maksymalnej wartości na każdym rzędzie zobaczyć Edycja:

from scipy.sparse import coo_matrix 
import numpy as np 
row = np.array([0, 3, 1, 0]) 
col = np.array([0, 2, 3, 2]) 
data = np.array([-3, 4, 11, -7]) 
A= coo_matrix((data, (row, col)), shape=(4, 4)) 
print A.toarray() 

nrRows=A.shape[0] 
maxrowind=[] 
for i in range(nrRows): 
    r = A.getrow(i)# r is 1xA.shape[1] matrix 
    maxrowind.append(r.indices[r.data.argmax()] if r.nnz else 0) 
print maxrowind 

r.nnz jest hrabia wyraźnie przechowywanych wartości (czyli wartości niezerowe)

+0

Czy to nie wystarczy, aby uzyskać jedną wartość, a nie dla każdego wiersza lub kolumny? –

+0

Tak, masz rację. Zobacz EDYCJĘ! – xecafe

3

Proponuję studiując kod

moo._min_or_max_axis 

gdzie moo jest coo_matrix.

mat = mat.tocsc() # for axis=0 
mat.sum_duplicates() 

major_index, value = mat._minor_reduce(min_or_max) 
not_full = np.diff(mat.indptr)[major_index] < N 
value[not_full] = min_or_max(value[not_full], 0) 

mask = value != 0 
major_index = np.compress(mask, major_index) 
value = np.compress(mask, value) 
return coo_matrix((value, (np.zeros(len(value)), major_index)), 
         dtype=self.dtype, shape=(1, M)) 

W zależności od osi woli pracować z csc nad csr. Nie miałem czasu analizować tego, ale przypuszczam, że powinno być możliwe uwzględnienie w obliczeniach wartości argmax.


Ta sugestia może nie działać. Kluczem jest metoda mat._minor_reduce, co robi, z pewnym wyrafinowaniem:

ufunc.reduceat(mat.data, mat.indptr[:-1]) 

To jest stosuje ufunc do bloków macierzy macierz data, używając indptr do definiowania bloków. np.sum, np.maxiumumufunc gdzie to działa. Nie znam odpowiednika o nazwie ufunc argmax.

Ogólnie rzecz biorąc, jeśli chcesz robić rzeczy według "wiersza" dla matrycy csr (lub kolumny csc), musisz albo powtórzyć wiersz, co jest stosunkowo kosztowne, albo użyć tego , aby zrobić to samo nad płaskim wektorem mat.data.

group argmax/argmin over partitioning indices in numpy próbuje wykonać argmax.reduceat. Rozwiązanie może być przystosowane do rzadkiej macierzy.

+0

Tak, http://stackoverflow.com/questions/22124332/group-argmax-argmin-over-partitioning-indices-in-numpy jest logicznie równoważny; po prostu zastosuj do "wskaźników" CSR "indeksu". – joeln

1

W najnowszej wersji pakietu numpy_indexed (Zastrzeżenie: Jestem jego autorem) może rozwiązać ten problem w sposób skuteczny i elegancki sposób:

import numpy_indexed as npi 
col, argmax = group_by(coo.col).argmax(coo.data) 
row = coo.row[argmax] 

Tu grupy przez kol, więc jej na argmax nad kolumnami ; zamiana wiersza i zmiennej col da ci argmax w wierszach.

0

Rozszerzenie na odpowiedziach z @hpaulj i @joeln i za pomocą kodu z group argmax/argmin over partitioning indices in numpy jak sugeruje, ta funkcja oblicza argmax nad kolumn dla CSR lub argmax nad rzędami dla CSC:

import numpy as np 
import scipy.sparse as sp 

def csr_csc_argmax(X, axis=None): 
    is_csr = isinstance(X, sp.csr_matrix) 
    is_csc = isinstance(X, sp.csc_matrix) 
    assert(is_csr or is_csc) 
    assert(not axis or (is_csr and axis==1) or (is_csc and axis==0)) 

    major_size = X.shape[0 if is_csr else 1] 
    major_lengths = np.diff(X.indptr) # group_lengths 
    major_not_empty = (major_lengths > 0) 

    result = -np.ones(shape=(major_size,), dtype=X.indices.dtype) 
    split_at = X.indptr[:-1][major_not_empty] 
    maxima = np.zeros((major_size,), dtype=X.dtype) 
    maxima[major_not_empty] = np.maximum.reduceat(X.data, split_at) 
    all_argmax = np.flatnonzero(np.repeat(maxima, major_lengths) == X.data) 
    result[major_not_empty] = X.indices[all_argmax[np.searchsorted(all_argmax, split_at)]] 
    return result 

Zwraca -1 argmax dowolnych wierszy (CSR) lub kolumn (CSC), które są całkowicie rzadkie (tj. są całkowicie zerowe po X.eliminate_zeros()).