忽略稀疏矩阵中的重复条目
问题描述
我尝试从(data, (rows, cols))
值列表中初始化csc_matrix
和csr_matrix
,正如文档所建议的那样。
sparse = csc_matrix((data, (rows, cols)), shape=(n, n))
问题是,我实际用于生成data
、rows
和cols
向量的方法为某些点引入了重复项。默认情况下,scipy将重复条目的值相加。然而,在我的例子中,对于给定的(row, col)
,这些重复项在data
中具有完全相同的值。
我试图实现的是让Scipy忽略第二个条目(如果已经存在),而不是添加它们。
忽略我可以改进生成算法以避免生成重复项的事实,是否有参数或其他方法可以创建忽略重复项的稀疏矩阵?
当前有两个data = [4, 4]; cols = [1, 1]; rows = [1, 1];
条目生成稀疏矩阵,(1,1)
处的值为8
,而所需值为4
。
>>> c = csc_matrix(([4, 4], ([1,1],[1,1])), shape=(3,3))
>>> c.todense()
matrix([[0, 0, 0],
[0, 8, 0],
[0, 0, 0]])
我还知道我可以使用二维NumPyunique
函数来筛选它们,但列表非常大,因此这实际上不是一个有效的选项。
min
或max
而不是默认的sum
?
解决方案
创建中间矩阵dok
在您的示例中起作用:
In [410]: c=sparse.coo_matrix((data, (cols, rows)),shape=(3,3)).todok().tocsc()
In [411]: c.A
Out[411]:
array([[0, 0, 0],
[0, 4, 0],
[0, 0, 0]], dtype=int32)
coo
矩阵将您的输入数组原封不动地放入其data
、col
、row
属性中。除非将其转换为csc
,否则不会进行求和。
todok
直接从coo
属性加载词典。它创建空的dok
矩阵,并用:填充
dok.update(izip(izip(self.row,self.col),self.data))
因此,如果有重复的(row,col)
值,则是剩余的最后一个值。这使用标准的Python字典散列来查找唯一键。
这里有一种使用np.unique
的方法。我必须构造一个特殊的对象数组,因为unique
在1D上操作,而我们有一个2D索引。
In [479]: data, cols, rows = [np.array(j) for j in [[1,4,2,4,1],[0,1,1,1,2],[0,1,2,1,1]]]
In [480]: x=np.zeros(cols.shape,dtype=object)
In [481]: x[:]=list(zip(rows,cols))
In [482]: x
Out[482]: array([(0, 0), (1, 1), (2, 1), (1, 1), (1, 2)], dtype=object)
In [483]: i=np.unique(x,return_index=True)[1]
In [484]: i
Out[484]: array([0, 1, 4, 2], dtype=int32)
In [485]: c1=sparse.csc_matrix((data[i],(cols[i],rows[i])),shape=(3,3))
In [486]: c1.A
Out[486]:
array([[1, 0, 0],
[0, 4, 2],
[0, 1, 0]], dtype=int32)
我不知道哪种方法更快。
另一种获取唯一索引的方法,如liuengo's
链接:
rc = np.vstack([rows,cols]).T.copy()
dt = rc.dtype.descr * 2
i = np.unique(rc.view(dt), return_index=True)[1]
rc
必须拥有自己的数据才能使用VIEW更改数据类型,因此.T.copy()
。
In [554]: rc.view(dt)
Out[554]:
array([[(0, 0)],
[(1, 1)],
[(2, 1)],
[(1, 1)],
[(1, 2)]],
dtype=[('f0', '<i4'), ('f1', '<i4')])
相关文章