忽略稀疏矩阵中的重复条目
Ignoring duplicate entries in sparse matrix
我已尝试按照文档的建议从 (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]])
我也知道我可以使用二维 numpy unique
函数过滤它们,但是列表非常大,所以这不是一个真正有效的选项。
该问题的其他可能答案:是否有任何方法可以指定如何处理重复项?即保留 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)
A 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
link:
rc = np.vstack([rows,cols]).T.copy()
dt = rc.dtype.descr * 2
i = np.unique(rc.view(dt), return_index=True)[1]
rc
必须拥有自己的数据才能使用视图更改数据类型,因此 .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')])
由于你的data
在repeating (row, col)处的值是相同的,你可以得到唯一的行、列和值如下:
rows, cols, data = zip(*set(zip(rows, cols, data)))
示例:
data = [4, 3, 4]
cols = [1, 2, 1]
rows = [1, 3, 1]
csc_matrix((data, (rows, cols)), shape=(4, 4)).todense()
matrix([[0, 0, 0, 0],
[0, 8, 0, 0],
[0, 0, 0, 0],
[0, 0, 3, 0]])
rows, cols, data = zip(*set(zip(rows, cols, data)))
csc_matrix((data, (rows, cols)), shape=(4, 4)).todense()
matrix([[0, 0, 0, 0],
[0, 4, 0, 0],
[0, 0, 0, 0],
[0, 0, 3, 0]])
只是为了更新 hpaulj 对最新版本 SciPy 的回答,这个问题最简单的解决方案是现在,给定一个 COO 矩阵 c
现在:
dok=sparse.dok_matrix((c.shape),dtype=c.dtype)
dok._update(zip(zip(c.row,c.col),c.data))
new_c = dok.tocsc()
这是由于dokupdate()
函数中的一个新的包装器,阻止它直接改变数组,需要使用下划线来绕过包装器。
我已尝试按照文档的建议从 (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]])
我也知道我可以使用二维 numpy unique
函数过滤它们,但是列表非常大,所以这不是一个真正有效的选项。
该问题的其他可能答案:是否有任何方法可以指定如何处理重复项?即保留 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)
A 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
link:
rc = np.vstack([rows,cols]).T.copy()
dt = rc.dtype.descr * 2
i = np.unique(rc.view(dt), return_index=True)[1]
rc
必须拥有自己的数据才能使用视图更改数据类型,因此 .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')])
由于你的data
在repeating (row, col)处的值是相同的,你可以得到唯一的行、列和值如下:
rows, cols, data = zip(*set(zip(rows, cols, data)))
示例:
data = [4, 3, 4]
cols = [1, 2, 1]
rows = [1, 3, 1]
csc_matrix((data, (rows, cols)), shape=(4, 4)).todense()
matrix([[0, 0, 0, 0],
[0, 8, 0, 0],
[0, 0, 0, 0],
[0, 0, 3, 0]])
rows, cols, data = zip(*set(zip(rows, cols, data)))
csc_matrix((data, (rows, cols)), shape=(4, 4)).todense()
matrix([[0, 0, 0, 0],
[0, 4, 0, 0],
[0, 0, 0, 0],
[0, 0, 3, 0]])
只是为了更新 hpaulj 对最新版本 SciPy 的回答,这个问题最简单的解决方案是现在,给定一个 COO 矩阵 c
现在:
dok=sparse.dok_matrix((c.shape),dtype=c.dtype)
dok._update(zip(zip(c.row,c.col),c.data))
new_c = dok.tocsc()
这是由于dokupdate()
函数中的一个新的包装器,阻止它直接改变数组,需要使用下划线来绕过包装器。