2015-06-09 20 views
12

scipy.sparse.coo_matrix.max restituisce il valore massimo di ogni riga o colonna, dato un asse. Vorrei sapere non il valore, ma l'indice del valore massimo di ogni riga o colonna. Non ho ancora trovato un modo per rendere questo in modo efficiente, quindi accetterò volentieri qualsiasi aiuto.Argmax di ogni riga o colonna nella matrice sparsa scipy

+0

Si potrebbe provare questo: http://stackoverflow.com/a/9337071/1738214 elabora ogni riga separatamente – gcucurull

risposta

2

Da scipy versione 0.19, entrambi i metodi csr_matrix e csc_matrix supportano argmax() e argmin().

1

Se A è la vostra scipy.sparse.coo_matrix, allora si ottiene la riga e la colonna del valore massimo come segue:

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

per ottenere l'indice del valore massimo su ogni riga vedere la modifica sotto:

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 è il il conteggio dei valori esplicitamente-memorizzati (cioè valori diversi da zero)

+0

Questo non produrrebbe solo un singolo valore, non per ogni riga o colonna? –

+0

Sì, hai ragione. Guarda l'EDIT! – xecafe

3

Vorrei suggerire a studiare il codice per

moo._min_or_max_axis 

dove moo è un 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)) 

A seconda dell'asse, preferisce lavorare con csc over csr. Non ho avuto il tempo di analizzare questo, ma suppongo che dovrebbe essere possibile includere argmax nel calcolo.


Questo suggerimento potrebbe non funzionare. La chiave è il metodo mat._minor_reduce, che fa, con alcuni perfezionamenti:

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

Cioè è applicato il ufunc a blocchi della matrice data, usando l'indptr per definire i blocchi. np.sum, np.maxiumum sono ufunc dove funziona. Non so di un equivalente argmax ufunc.

In generale, se si desidera eseguire le operazioni in 'riga' per una matrice csr (o colonna di csc), è necessario iterare sulle righe, che è relativamente costoso, o utilizzare questo per fare la stessa cosa sul vettore piatto mat.data.

group argmax/argmin over partitioning indices in numpy tenta di eseguire un argmax.reduceat. La soluzione potrebbe essere adattabile a una matrice sparsa.

+0

Sì, http://stackoverflow.com/questions/22124332/group-argmax-argmin-over-partitioning-indices-in-numpy è logicamente equivalente; basta applicare a 'indici' e 'indptr' di una CSR. – joeln

1

L'ultima versione del pacchetto numpy_indexed (disclaimer: io sono il suo autore) può risolvere questo problema in modo efficiente ed elegante:

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

Qui gruppo da Col, per cui il suo l'argmax sulle colonne ; lo scambio di riga e colonna ti darà l'argmax sopra le righe.

0

Ampliando le risposte da @hpaulj e @joeln e utilizzando il codice da group argmax/argmin over partitioning indices in numpy come suggerito, questa funzione calcola argmax sopra colonne di CSR o argmax sopra le righe per il 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 

Esso restituisce -1 per l'argmax di tutte le righe (CSR) o colonne (CSC) che sono completamente sparse (cioè che sono completamente zero dopo X.eliminate_zeros()).

Problemi correlati