提取一些列后,sparse_csc矩阵的索引会反转

时间:2017-08-08 15:37:23

标签: python scipy sparse-matrix

我正在尝试提取scipy稀疏列矩阵的列,但结果不会像我期望的那样存储。这就是我的意思:

In [77]: a = scipy.sparse.csc_matrix(np.ones([4, 5]))
In [78]: ind = np.array([True, True, False, False, False])
In [79]: b = a[:, ind]

In [80]: b.indices
Out[80]: array([3, 2, 1, 0, 3, 2, 1, 0], dtype=int32)

In [81]: a.indices
Out[81]: array([0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3], dtype=int32)

为什么b.indices不是[0, 1, 2, 3, 0, 1, 2, 3]? 既然这种行为不是我所期望的,那么a[:, ind]不是从csc矩阵中提取列的正确方法吗?

2 个答案:

答案 0 :(得分:1)

索引未排序。您可以通过反转行来强制循环,这不是那么直观,或强制执行排序索引(您也可以就地执行,但我更喜欢强制转换)。我觉得有趣的是has_sorted_indices属性并不总是返回一个布尔值,而是将它与整数表示混合。

a = scipy.sparse.csc_matrix(np.ones([4, 5]))
ind = np.array([True, True, False, False, False])
b = a[::-1, ind]
b2 = a[:, ind]
b3 = b2.sorted_indices()

b.indices
>>array([0, 1, 2, 3, 0, 1, 2, 3], dtype=int32)
b.has_sorted_indices
>>1
b2.indices
>>array([3, 2, 1, 0, 3, 2, 1, 0], dtype=int32)
b2.has_sorted_indices
>>0
b3.indices
array([0, 1, 2, 3, 0, 1, 2, 3], dtype=int32)
b3.has_sorted_indices
>>True

答案 1 :(得分:1)

csccsr索引不保证排序。我无法找到效果的文档,但has_sort_indicessort方法表明了这一点。

在您的情况下,订单是索引编制方式的结果。我在之前的SO问题中发现,多列索引是使用矩阵乘法执行的:

In [165]: a = sparse.csc_matrix(np.ones([4,5]))
In [166]: b = a[:,[0,1]]
In [167]: b.indices
Out[167]: array([3, 2, 1, 0, 3, 2, 1, 0], dtype=int32)

此索引相当于构建“选择”矩阵:

In [169]: I = sparse.csr_matrix(np.array([[1,0,0,0,0],[0,1,0,0,0]]).T)
In [171]: I.A
Out[171]: 
array([[1, 0],
       [0, 1],
       [0, 0],
       [0, 0],
       [0, 0]], dtype=int32)

并执行此矩阵乘法:

In [172]: b1 = a * I
In [173]: b1.indices
Out[173]: array([3, 2, 1, 0, 3, 2, 1, 0], dtype=int32)

顺序是矩阵乘法如何完成的结果。实际上a * a.T做了同样的逆转。我们必须检查乘法代码以确切知道原因。显然,csccsr计算代码不需要排序indices,也不会确保对结果进行排序。

https://docs.scipy.org/doc/scipy-0.19.1/reference/sparse.html#further-details

  

更多细节¶   CSR列索引不一定要排序。同样对于CSC行索引。当需要排序索引时(例如,将数据传递给其他库时),请使用.sorted_indices()和.sort_indices()方法。