Scipy相当于numpy稀疏矩阵的位置

时间:2014-08-05 17:51:46

标签: python numpy scipy sparse-matrix

我正在寻找与scipy offer(numpy.where)的稀疏表示一起使用的等效scipy.sparse。 是否有任何东西可以让你处理这些矩阵,就好像你在那里使用if-then-else语句一样?

更新 更具体一点:我需要where作为if-then-else矢量化函数,即在诸如对于矩阵A中等于K的每个值的任务中,将相应的值放在矩阵B中,否则C. 您可以使用find之类的东西来检索那些满足逻辑条件的条目的索引,然后否定它们以找到所有剩余的条目,但对于稀疏矩阵,是不是有更紧凑的方法?

3 个答案:

答案 0 :(得分:5)

您可以使用scipy.sparse.find(http://docs.scipy.org/doc/scipy-0.9.0/reference/generated/scipy.sparse.find.html)。 此函数返回稀疏矩阵的非负值。 对于某种情况,你可以使用,即:

 import scipy.sparse as sp
 A = sp.csr_matrix([[1, 2, 0], [0, 0, 3], [4, 0, 5]])
 B = A > 2 #the condition
 indexes = sp.find(B)

答案 1 :(得分:2)

np.wherecondx匹配大小稀疏的矩阵时,这是一个重复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)
带有x和y的

np.where相当于:

[xv if c else yv for (c,xv,yv) in zip(condition,x,y)]  # see doc

C代码可能使用nditer实现此功能,其功能类似于zip,逐步执行输入和输出的所有元素。如果输出接近密集(例如y=2),那么np.where将比这个稀疏替代更快。

答案 2 :(得分:0)

这是我用np.where代替稀疏矩阵的find

def where(mask, val, arr):
    """ Sparse `where` """
    out = arr.copy()
    rows, cols, _ = find(mask)
    for r, c in zip(rows, cols):
        out[r, c] = val
    return out