如何获得稀疏矩阵的视图?

时间:2018-08-26 00:46:55

标签: python python-3.x numpy scipy

切片numpy数组时,我们获得了对应数据的视图。但是,scipy.sparse中的稀疏矩阵似乎并非如此。尽管the docs简短地提到了对lil_matrix类的切片,但尚不清楚如何(或是否)可以获取数据视图。

至少通过使用以下示例脚本,我未能成功获得稀疏矩阵的视图:

import numpy as np
from scipy.sparse import lil_matrix


def test(matrix):
    print('\n=== Testing {} ==='.format(type(matrix)))

    a = matrix[:, 0]
    b = matrix[0, :]

    a[0] = 100
    M[0, 1] = 200
    M[1, 0] = 200
    print('a = '); print(a)
    print('b = '); print(b)


M = np.arange(4).reshape(2, 2) + 1
S = lil_matrix(M)

test(M)
test(S)

哪个输出:

=== Testing <class 'numpy.ndarray'> ===
a = 
[100 200]
b = 
[100 200]

=== Testing <class 'scipy.sparse.lil.lil_matrix'> ===
a = 
  (0, 0)    100
  (1, 0)    3
b = 
  (0, 0)    1
  (0, 1)    2

经过测试 Python 3.6.6, numpy==1.14.5, scipy==1.1.0

1 个答案:

答案 0 :(得分:1)

我会部分地吃我的话。有一种lilmatrix getrowview方法(但没有getcolview)。

lil矩阵具有2个对象dtype数组属性datarows。两者都包含列表,每行一个。

def getrow(self, i):
    """Returns a copy of the 'i'th row.
    """
    i = self._check_row_bounds(i)
    new = lil_matrix((1, self.shape[1]), dtype=self.dtype)
    new.rows[0] = self.rows[i][:]
    new.data[0] = self.data[i][:]
    return new

def getrowview(self, i):
    """Returns a view of the 'i'th row (without copying).
    """
    new = lil_matrix((1, self.shape[1]), dtype=self.dtype)
    new.rows[0] = self.rows[i]
    new.data[0] = self.data[i]
    return new

一些测试表明,修改行视图的元素确实会影响父级和v.v。

view之所以有效,是因为对象数组包含指针。与列表中的指针一样,它们可以共享。而且,如果操作正确,可以就地修改此类列表。

我是通过在view文档上对lil_matrix进行页面搜索来发现这一点的。我找不到其他格式的相似之处。

有些csr格式的数字函数可直接与.data属性一起使用。如果您不更改稀疏性,而只想修改非零值,则可以这样做。并且可以在适当位置修改该属性。在有限的情况下,可以构造一个新的稀疏矩阵来共享另一个数据属性的切片,但是它不像ndarray切片那样普遍。


In [88]: M = sparse.lil_matrix((4,10),dtype=int)
In [89]: M[0,1::2] = 1
In [90]: M[1,::2] = 2
In [91]: M1 = M.getrowview(0)

In [92]: M1[0,::2] = 3
In [94]: M.A
Out[94]: 
array([[3, 1, 3, 1, 3, 1, 3, 1, 3, 1],
       [2, 0, 2, 0, 2, 0, 2, 0, 2, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

In [95]: M[0,1::2] = 4
In [97]: M1.A
Out[97]: array([[3, 4, 3, 4, 3, 4, 3, 4, 3, 4]])

按照此模型,我可以创建“ advanced-index view, something that ndarray”不起作用:

In [98]: M2 = sparse.lil_matrix((2,10), dtype=int)
In [99]: M2.rows[:] = M.rows[[0,3]]
In [100]: M2.data[:] = M.data[[0,3]]
In [101]: M2.A
Out[101]: 
array([[3, 4, 3, 4, 3, 4, 3, 4, 3, 4],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
In [102]: M2[:,::2] *= 10
In [103]: M2.A
Out[103]: 
array([[30,  4, 30,  4, 30,  4, 30,  4, 30,  4],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0]])
In [104]: M1.A
Out[104]: array([[30,  4, 30,  4, 30,  4, 30,  4, 30,  4]])