Q:

Restricting a sparse matrix to a subspace in scipy

Say I have a square NxN crs matrix in spicy. I'd like to restrict that matrix to a subspace, by keeping M indices (given by an array of N booleans, M of which are true). This should give me an MxM sparse matrix.
So obviously one way to do that is to extract the coefficients as an array of data and two arrays of coordinates and renumber the coordinates using a sort. This is painful and bit ugly.
Isn't there a function, or perhaps a library call to do that?

A:

If y is a sparse matrix:
In [56]: y
Out[56]: 
<200x200 sparse matrix of type '<type 'numpy.float64'>'
    with 197 stored elements in Compressed Sparse Row format>

and mask is a 1-dimensional boolean array:
In [57]: mask.dtype
Out[57]: dtype('bool')

In [58]: mask.shape
Out[58]: (200,)

Then y[mask][:, mask] yields the desired submatrix:
In [59]: y[mask][:, mask]
Out[59]: 
<103x103 sparse matrix of type '<type 'numpy.float64'>'
    with 51 stored elements in Compressed Sparse Row format>

NumPy also has a function np.ix_ which you could use here to construct the desired index, but it is considerably slower:
In [64]: y[np.ix_(mask, mask)]
Out[64]: 
<103x103 sparse matrix of type '<type 'numpy.float64'>'
    with 51 stored elements in Compressed Sparse Row format>

In [65]: %timeit y[np.ix_(mask, mask)]
10 loops, best of 3: 59.8 ms per loop

In [66]: %timeit y[mask][:, mask]
1000 loops, best of 3: 494 µs per loop

Note that both y[mask][:, mask] and y[np.ix_(mask, mask)] return new sparse matrices, not views of the original sparse matrix. Since you are selecting arbitrary rows and columns, there is no way to return a view.
However, since y[np.ix_(mask, mask)] uses only one index, assignments to it call y.__setitem__ (a method of y) and thus affect y:
y[np.ix_(mask, mask)] = other

In contrast, since y[mask] is a matrix independent of y, 
the assignment 
y[mask][:, mask] = other

calls the __setitem__ method of this independent matrix and thus has no effect on y.

