【问题标题】:expanding (adding a row or column) a scipy.sparse matrix扩展(添加行或列) scipy.sparse 矩阵
【发布时间】:2011-06-09 09:10:27
【问题描述】:

假设我有一个来自 scipy.sparse 的 NxN 矩阵 M(lil_matrix 或 csr_matrix),我想将其设为 (N+1)xN,其中 M_modified[i,j] = M[i,j] 为 0

【问题讨论】:

标签: python scipy sparse-matrix


【解决方案1】:

Scipy 无法在不复制数据的情况下执行此操作,但您可以通过更改定义稀疏矩阵的属性自行完成。

构成 csr_matrix 的属性有 4 个:

data:包含矩阵中实际值的数组

indices:一个数组,包含与data中每个值对应的列索引

indptr:一个数组,指定每行数据中第一个值之前的索引。如果该行为空,则索引与上一列相同。

shape:包含矩阵形状的元组

如果您只是在底部添加一行零,您只需更改矩阵的形状和 indptr。

x = np.ones((3,5))
x = csr_matrix(x)
x.toarray()
>> array([[ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.]])
# reshape is not implemented for csr_matrix but you can cheat and do it  yourself.
x._shape = (4,5)
# Update indptr to let it know we added a row with nothing in it. So just append the last
# value in indptr to the end.
# note that you are still copying the indptr array
x.indptr = np.hstack((x.indptr,x.indptr[-1]))
x.toarray()
array([[ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 0.,  0.,  0.,  0.,  0.]])

这是一个处理更一般的 vstacking 任意 2 个 csr_matrices 情况的函数。您最终仍然会复制底层的 numpy 数组,但它仍然比 scipy vstack 方法快得多。

def csr_vappend(a,b):
    """ Takes in 2 csr_matrices and appends the second one to the bottom of the first one. 
    Much faster than scipy.sparse.vstack but assumes the type to be csr and overwrites
    the first matrix instead of copying it. The data, indices, and indptr still get copied."""

    a.data = np.hstack((a.data,b.data))
    a.indices = np.hstack((a.indices,b.indices))
    a.indptr = np.hstack((a.indptr,(b.indptr + a.nnz)[1:]))
    a._shape = (a.shape[0]+b.shape[0],b.shape[1])
    return a

【讨论】:

  • 我认为你甚至可以不返回a,因为函数参数是通过引用传递的,a 即使在函数范围内也会被直接修改。另外,可以有 csc_happend(a,b) 模拟吗?
  • 好主意,简单地重置形状。
  • what are the implications of changing the shape as u suggested? 我试过你的方法,添加行效果很好,但是列中断,知道为什么吗?!
  • Spicy 确实提供了套路。看看下面 Sidhant 的答案,并给它一个 Thumps UP。 hstack 和 vstack 页面也为您提供了简单的示例代码。
  • 袜子木偶警报
【解决方案2】:

不确定您是否仍在寻找解决方案,但也许其他人可以查看hstackvstack - http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.hstack.html。我认为我们可以为单个附加行定义一个 csr_matrix,然后将其与前一个矩阵一起 vstack

【讨论】:

  • source code for vstack 正如这所暗示的,它返回输入矩阵的新副本,因此如果我们想就地扩展矩阵,效率不够。
【解决方案3】:

我认为没有任何方法可以真正摆脱复制。这两种类型的稀疏矩阵都在内部将它们的数据存储为 Numpy 数组(在 csr 的数据和索引属性中以及在 lil 的数据和行属性中),并且 Numpy 数组无法扩展。

更新更多信息:

LIL 确实代表链接列表,但当前的实现并不完全符合名称。用于datarows 的 Numpy 数组都是对象类型。这些数组中的每个对象实际上都是 Python 列表(当所有值连续为零时为空列表)。 Python 列表并不完全是链表,但由于 O(1) 查找,它们有点接近并且坦率地说是更好的选择。就个人而言,我没有立即看到在这里使用 Numpy 对象数组而不仅仅是 Python 列表的意义。您可以相当轻松地将当前的 lil 实现更改为使用 Python 列表,这将允许您在不复制整个矩阵的情况下添加一行。

【讨论】:

  • 如果它对您的应用程序足够重要,您可以使用 scipy.sparse 接口实现一个新类,该接口使用更容易扩展的数据类型。
  • 也许对底层数据结构更了解的人可以回答这个问题。我以为 lil_matrix 是用链表实现的?
  • @scandido,看看我的最新添加是否回答了你的问题。
  • Spicy 确实提供了套路。看看下面 Sidhant 的回答并竖起大拇指。 hstack 和 vstack 页面也为您提供了简单的示例代码。
猜你喜欢
  • 2011-05-18
  • 1970-01-01
  • 2015-11-04
  • 2014-07-19
  • 2023-04-09
  • 2012-05-28
  • 2018-09-05
  • 2014-10-21
  • 2011-09-19
相关资源
最近更新 更多