如何使用稀疏矩阵(在scipy.sparse中)构建dtypes?

时间:2018-02-07 23:51:22

标签: python numpy matrix scipy sparse-matrix

我有结构化数据,可以用numpy表示,如下所示:

dtype = np.dtype([('a', 'f8'),
                  ('b', 'f8')])
X = np.zeros((3,4), dtype=dtype)

并希望在它的稀疏版本上运行。 Scipy有sparse,但我还没有弄明白如何实现结构化数据:

import numpy as np
import scipy.sparse as sparse

dtype = np.dtype([('a', 'f8'),
                  ('b', 'f8')])
X = np.zeros((3,4), dtype=dtype)
A, B = X['a'], X['b']
A[:] = np.arange(0, 12).reshape((3,4))

Xdok = sparse.dok_matrix(X, dtype=dtype)
Xcoo = Xdoc.tocoo()

# No supported conversion for structured type
# Xcsr = Xdok.tocsr()
# Xlil = Xdok.tolil()

# Cannot perform reduce with flexible type
# Xdok['a']

# 'coo_matrix' object is not subscriptable
# Xcoo['a']

我可以获得doccoo版本,但之后我无法切出我的密钥(例如Xdok['a']),而且根据我的理解,{{1并且dok在执行任何类型的数学运算时都是低效的。

最终,我试图用边缘上的多值权重来表示有向图(例如cooa),我需要能够执行简单的线性代数图表。

我考虑将b稀疏矩阵与a稀疏矩阵分开,但最终它们将填充在完全相同的索引中,我宁愿保留所有内存中一个结构中的数据。

我应该使用另一个lib而不是Scipy吗?

1 个答案:

答案 0 :(得分:1)

In [26]: M = sparse.coo_matrix(X)
In [27]: M.data
Out[27]: 
array([( 1., 0.), ( 2., 0.), ( 3., 0.), ( 4., 0.), ( 5., 0.), ( 6., 0.),
       ( 7., 0.), ( 8., 0.), ( 9., 0.), (10., 0.), (11., 0.)],
      dtype=[('a', '<f8'), ('b', '<f8')])
In [28]: M.A
....
ValueError: unsupported data types in input

In [30]: M.tocsr()
...
TypeError: no supported conversion for types: (dtype([('a', '<f8'), ('b', '<f8')]),)

使用化合物dtype转换为(和来自)dok

In [31]: M.todok()
Out[31]: 
<3x4 sparse matrix of type '<class 'numpy.void'>'
    with 11 stored elements in Dictionary Of Keys format>
In [32]: _.items()
Out[32]: dict_items([((0, 1), (1., 0.)), ((1, 2), (6., 0.)), ((1, 3), (7., 0.)), ((2, 3), (11., 0.)), ((2, 0), (8., 0.)), ((1, 0), (4., 0.)), ((0, 3), (3., 0.)), ((2, 2), (10., 0.)), ((1, 1), (5., 0.)), ((2, 1), (9., 0.)), ((0, 2), (2., 0.))])

dok实现索引:

In [33]: __[0,1]
Out[33]: (1., 0.)

M.data数组是结构化的,可以通过字段名称访问。但coo尚未实施任何索引:

In [34]: M.data['a']
Out[34]: array([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11.])

dok是字典的子类,显然元素存储为dtype记录:

In [39]: type(M.todok()[0,1])
Out[39]: numpy.void
In [40]: M.todok()[0,1]['a']
Out[40]: 1.0

但同样,dok索引中没有用于访问字段的规定。

总而言之,稀疏模块并未考虑复合dtypes。它的根源是线性代数(例如求解大型稀疏线性方程)。这些dtypes工作的地方就是使用numpy数组和元素而无需特殊处理。