【问题标题】:Scipy equivalent of numpy where for sparse matricesScipy 等价于 numpy where 用于稀疏矩阵
【发布时间】:2014-09-28 11:53:18
【问题描述】:

我正在寻找与 scipy 提供的稀疏表示 (scipy.sparse) 一起使用的 numpy.where 的等价物。 有什么东西可以让你处理这些矩阵,就好像你在哪里使用 if-then-else 语句一样?

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

【问题讨论】:

  • 你对A==kBC的稀疏性了解多少?如果A==k 非常稀疏,那么A!=k 将几乎是密集的。它可能会给你一个SparseEfficiencyWarning
  • 有可能,但我相信这不是重点

标签: python numpy scipy sparse-matrix


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    这是一个复制np.where 的函数,当condxy 是匹配大小的稀疏矩阵时。

    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 将比这个稀疏替代更快。

    【讨论】:

      【解决方案3】:

      您可以使用 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)
      

      【讨论】:

      • findwhere 不同,即使在不同的矩阵上也可以进行更复杂的操作
      • 所以find 不一样,但它可以用来做你想做的事吗?也许你应该编辑你的问题更具体。
      猜你喜欢
      • 2017-11-03
      • 2013-09-24
      • 1970-01-01
      • 1970-01-01
      • 2013-10-10
      • 1970-01-01
      • 2014-12-21
      • 2016-01-24
      • 2017-03-26
      相关资源
      最近更新 更多