2015-02-23 30 views
5

如文档所示,我试图从(data, (rows, cols))值列表中初始化csc_matrixcsr_matrix忽略稀疏矩阵中的重复条目

sparse = csc_matrix((data, (rows, cols)), shape=(n, n)) 

的问题是,我实际上有用于产生datarowscols矢量的方法引入了对某些点重复。默认情况下,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]]) 

我也知道,我可以用一个2维numpy的unique功能进行筛选,但名单是相当大的,所以这是不是一个真正的有效选项。

问题的其他可能的答案:有没有任何方式指定如何处理重复?即保留minmax而不是默认的sum

+0

我很确定答案是否定的,没有内置的方式来改变重复的行为。尽管如此,你不应该太过放弃使用'np.unique':无论你的列表有多大,scipy都会将它们转换为数组,并在引擎盖下做类似的操作,所以你没有理由不应该尝试。 – Jaime 2015-02-23 16:53:40

+1

'np.unique'是1d,因此处理这些2d坐标需要一些额外的努力。 – hpaulj 2015-02-23 20:51:08

+1

是的,但是像[这个](http://stackoverflow.com/questions/16970982/find-unique-rows-in-numpy-array)这样的技巧使它成为2D。 – 2015-02-23 21:02:44

回答

4

创建一个中介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矩阵把您的输入数组到其datacolrow属性没有改变。直到它被转换为csc才会发生求和。

​​直接从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具有拥有以改变可观看D型,因此.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')]) 
+0

看起来很不错。我现在无法尝试,它需要花费很多时间/内存类型之间的转换吗? – 2015-02-23 21:06:02

+0

todok()不会忽略scipy中的重复项0.19 – 2017-09-13 03:22:45

+0

是的,'coo.todok'现在包含'self.sum_duplicates()'行。解决方案是按照我的描述进行更新,但没有这个“总和”。 – hpaulj 2017-09-13 05:08:25