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
risposta
Da scipy versione 0.19, entrambi i metodi csr_matrix
e csc_matrix
supportano argmax()
e argmin()
.
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)
Questo non produrrebbe solo un singolo valore, non per ogni riga o colonna? –
Sì, hai ragione. Guarda l'EDIT! – xecafe
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.
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
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.
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()
).
Si potrebbe provare questo: http://stackoverflow.com/a/9337071/1738214 elabora ogni riga separatamente – gcucurull