Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reshape sparse matrix efficiently, Python, SciPy 0.12

In another post regarding resizing of a sparse matrix in SciPy the accepted answer works when more rows or columns are to be added, using scipy.sparse.vstack or hstack, respectively. In SciPy 0.12 the reshape or set_shape methods are still not implemented.

Are there some stabilished good practices to reshape a sparse matrix in SciPy 0.12? It would be nice to have some timing comparisons.

like image 716
Saullo G. P. Castro Avatar asked Dec 26 '22 04:12

Saullo G. P. Castro


1 Answers

I don't know of any established good practices, so here's a fairly straight-forward reshape function for a coo_matrix. It converts its argument to a coo_matrix, so it will actual work for other sparse formats (but it returns a coo_matrix).

from scipy.sparse import coo_matrix


def reshape(a, shape):
    """Reshape the sparse matrix `a`.

    Returns a coo_matrix with shape `shape`.
    """
    if not hasattr(shape, '__len__') or len(shape) != 2:
        raise ValueError('`shape` must be a sequence of two integers')

    c = a.tocoo()
    nrows, ncols = c.shape
    size = nrows * ncols

    new_size =  shape[0] * shape[1]
    if new_size != size:
        raise ValueError('total size of new array must be unchanged')

    flat_indices = ncols * c.row + c.col
    new_row, new_col = divmod(flat_indices, shape[1])

    b = coo_matrix((c.data, (new_row, new_col)), shape=shape)
    return b

Example:

In [43]: a = coo_matrix([[0,10,0,0],[0,0,0,0],[0,20,30,40]])

In [44]: a.A
Out[44]: 
array([[ 0, 10,  0,  0],
       [ 0,  0,  0,  0],
       [ 0, 20, 30, 40]])

In [45]: b = reshape(a, (2,6))

In [46]: b.A
Out[46]: 
array([[ 0, 10,  0,  0,  0,  0],
       [ 0,  0,  0, 20, 30, 40]])

Now, I'm sure there are several regular contributors here who can come up with something better (faster, more memory efficient, less filling... :)

like image 152
Warren Weckesser Avatar answered Dec 28 '22 17:12

Warren Weckesser