Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
464 views
in Technique[技术] by (71.8m points)

python 3.x - Get top-n items of every row in a scipy sparse matrix

After reading this similar question, I still can't fully understand how to go about implementing the solution im looking for. I have a sparse matrix, i.e.:

 import numpy as np
 from scipy import sparse
 arr = np.array([[0,5,3,0,2],[6,0,4,9,0],[0,0,0,6,8]])
 arr_csc = sparse.csc_matrix(arr)

I would like to efficiently get the top n items of each row, without converting the sparse matrix to dense. The end result should look like this (assuming n=2):

 top_n_arr = np.array([[0,5,3,0,0],[6,0,0,9,0],[0,0,0,6,8]])
 top_n_arr_csc = sparse.csc_matrix(top_n_arr)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

What is wrong with the linked answer? Does it not work in your case? or you just don't understand it? Or it isn't efficient enough?

I was going to suggest working out a means of finding the top values for a row of an lil format matrix, and apply that row by row. But I would just be repeating my earlier answer.


OK, my previous answer was a start, but lacked some details on iterating through the lol format. Here's a start; it probably could be cleaned up.

Make the array, and a lil version:

In [42]: arr = np.array([[0,5,3,0,2],[6,0,4,9,0],[0,0,0,6,8]])    
In [43]: arr_sp=sparse.csc_matrix(arr)
In [44]: arr_ll=arr_sp.tolil()

The row function from the previous answer:

def max_n(row_data, row_indices, n):
        i = row_data.argsort()[-n:]
        # i = row_data.argpartition(-n)[-n:]
        top_values = row_data[i]
        top_indices = row_indices[i]  # do the sparse indices matter?
        return top_values, top_indices, i

Iterate over the rows of arr_ll, apply this function and replace the elements:

In [46]: for i in range(arr_ll.shape[0]):
    d,r=max_n(np.array(arr_ll.data[i]),np.array(arr_ll.rows[i]),2)[:2]
    arr_ll.data[i]=d.tolist()
    arr_ll.rows[i]=r.tolist()
   ....:     

In [47]: arr_ll.data
Out[47]: array([[3, 5], [6, 9], [6, 8]], dtype=object)

In [48]: arr_ll.rows
Out[48]: array([[2, 1], [0, 3], [3, 4]], dtype=object)

In [49]: arr_ll.tocsc().A
Out[49]: 
array([[0, 5, 3, 0, 0],
       [6, 0, 0, 9, 0],
       [0, 0, 0, 6, 8]])

In the lil format, the data is stored in 2 object type arrays, as sublists, one with the data numbers, the other with the column indices.

Viewing the data attributes of sparse matrix is handy when doing new things. Changing those attributes has some risk, since it mess up the whole array. But it looks like the lil format can be tweaked like this safely.

The csr format is better for accessing rows than csc. It's data is stored in 3 arrays, data, indices and indptr. The lil format effectively splits 2 of those arrays into sublists based on information in the indptr. csr is great for math (multiplication, addition etc), but not so good when changing the sparsity (turning nonzero values into zeros).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...