Csr matrix: How to replace missing value with np.nan instead of 0?

Viewed 1112

It seems that csr_matrix fill missing value with 0 in default. So how to fill the missing value with np.nan?

from scipy.sparse import csr_matrix
row = np.array([0, 0, 1, 2, 2, 2])
col = np.array([0, 2, 2, 0, 1, 2])
data = np.array([0, 2, 3, 4, 5, 6])
csr_matrix((data, (row, col)), shape=(3, 3)).toarray()

Output:

array([[0, 0, 2],
       [0, 0, 3],
       [4, 5, 6]])

Expected:

array([[0, np.nan, 2],
       [np.nan, np.nan, 3],
       [4, 5, 6]])
3 Answers

Here is a workaround:

from scipy.sparse import csr_matrix
row = np.array([0, 0, 1, 2, 2, 2])
col = np.array([0, 2, 2, 0, 1, 2])
data = np.array([0, 2, 3, 4, 5, 6])

mask = csr_matrix(([1]*len(data), (row, col)), shape=(3, 3)).toarray()
mask[mask==0] = np.nan

csr_matrix((data, (row, col)), shape=(3, 3)).toarray() * mask

It's not possible with csr_matrix, which by definition stores nonzero elements.

If you really need those nans, just manipulate the dense result.

a=csr_matrix((data, (row, col)), shape=(3, 3)).toarray()
a[a == 0] = np.nan
def todense_fill(coo: sp.coo_matrix, fill_value: float) -> np.ndarray:
    """Densify a sparse COO matrix. Same as coo_matrix.todense()
    except it fills missing entries with fill_value instead of 0.
    """
    dummy_value = np.nan if not np.isnan(fill_value) else np.inf
    dummy_check = np.isnan if np.isnan(dummy_value) else np.isinf
    coo = coo.copy().astype(float)
    coo.data[coo.data == 0] = dummy_value
    out = np.array(coo.todense()).squeeze()
    out[out == 0] = fill_value
    out[dummy_check(out)] = 0
    return out
Related