这是一个复制np.where 的函数,当cond、x 和y 是匹配大小的稀疏矩阵时。
def where1(cond, x):
# elements of x where cond
row, col, data = sparse.find(cond) # effectively the coo format
data = np.ones(data.shape, dtype=x.dtype)
zs = sparse.coo_matrix((data, (row, col)), shape=cond.shape)
xx = x.tocsr()[row, col][0]
zs.data[:] = xx
zs = zs.tocsr()
zs.eliminate_zeros()
return zs
def where2(cond, y):
# elements of y where not cond
row, col, data = sparse.find(cond)
zs = y.copy().tolil() # faster for this than the csr format
zs[row, col] = 0
zs = zs.tocsr()
zs.eliminate_zeros()
return zs
def where(cond, x, y):
# like np.where but with sparse matrices
ws1 = where1(cond, x)
# ws2 = where1(cond==0, y) # cond==0 is likely to produce a SparseEfficiencyWarning
ws2 = where2(cond, y)
ws = ws1 + ws2
# test against np.where
w = np.where(cond.A, x.A, y.A)
assert np.allclose(ws.A, w)
return ws
m,n, d = 100,90, 0.5
cs = sparse.rand(m,n,d)
xs = sparse.rand(m,n,d)
ys = sparse.rand(m,n,d)
print where(cs, xs, ys).A
即使在弄清楚如何编写 where1 之后,还需要进一步思考才能找到一种方法来应用问题的 not 方面而不产生警告。它不像密集的where 那样通用或快速,但它说明了以这种方式构建稀疏矩阵所涉及的复杂性。
值得注意的是
np.where(cond) == np.nonzero(cond) # see doc
xs.nonzero() == (xs.row, xs.col) # for coo format
sparse.find(xs) == (row, col, data)
np.where 与 x 和 y 等价于:
[xv if c else yv for (c,xv,yv) in zip(condition,x,y)] # see doc
C 代码可能使用nditer 来实现这一点,它在功能上类似于zip,单步执行输入和输出的所有元素。如果输出接近密集(例如y=2),则np.where 将比这个稀疏替代更快。