构造稀疏数组
通过坐标和数据
您可以从坐标和值数据构建 sparse.COO
数组。
cords
参数包含数据非零的索引,data
参数包含与这些索引对应的数据。例如,以下代码将生成一个 \(5 \times 5\) 对角矩阵
>>> import sparse
>>> coords = [[0, 1, 2, 3, 4],
... [0, 1, 2, 3, 4]]
>>> data = [10, 20, 30, 40, 50]
>>> s = sparse.COO(coords, data, shape=(5, 5))
>>> s
<COO: shape=(5, 5), dtype=int64, nnz=5, fill_value=0>
0 1 2 3 4
┌ ┐
0 │ 10 │
1 │ 20 │
2 │ 30 │
3 │ 40 │
4 │ 50 │
└ ┘
通常,coords
应该是一个形状为 (ndim, nnz)
的数组。coords
的每一行包含所需稀疏数组的一个维度,每一列包含与该非零元素对应的索引。data
包含与 coords
中的索引对应的数组的非零元素。它的形状应为 (nnz,)
。
如果 data
在所有坐标上都相同,它可以作为标量传入。例如,以下代码会生成一个 \(4 \times 4\) 单位矩阵
>>> import sparse
>>> coords = [[0, 1, 2, 3],
... [0, 1, 2, 3]]
>>> data = 1
>>> s = sparse.COO(coords, data, shape=(4, 4))
>>> s
<COO: shape=(4, 4), dtype=int64, nnz=4, fill_value=0>
0 1 2 3
┌ ┐
0 │ 1 │
1 │ 1 │
2 │ 1 │
3 │ 1 │
└ ┘
您可以(也应该)为 coords
和 data
传入 numpy.ndarray
对象。
在这种情况下,结果数组的形状是根据每个维度中的最大索引确定的。如果数组超出 coords
中的最大索引,您应该显式提供一个形状。例如,如果我们在不使用 shape
关键字参数的情况下执行以下操作,将得到一个 \(4 \times 5\) 矩阵,但我们可能实际想要一个 \(5 \times 5\) 的矩阵。
>>> coords = [[0, 3, 2, 1], [4, 1, 2, 0]]
>>> data = [1, 4, 2, 1]
>>> s = COO(coords, data, shape=(5, 5))
>>> s
<COO: shape=(5, 5), dtype=int64, nnz=4, fill_value=0>
0 1 2 3 4
┌ ┐
0 │ 1 │
1 │ 1 │
2 │ 2 │
3 │ 4 │
4 │ │
└ ┘
sparse.COO
数组支持任意填充值。填充值是“默认”值,或不存储的值。这可以被赋予一个非零值。例如,以下代码构建了一个(不好的) \(2 \times 2\) 单位矩阵表示。请注意,对于具有非零填充值的操作,并非所有操作都受支持。
>>> coords = [[0, 1], [1, 0]]
>>> data = [0, 0]
>>> s = COO(coords, data, fill_value=1)
>>> s
<COO: shape=(2, 2), dtype=int64, nnz=2, fill_value=1>
0 1
┌ ┐
0 │ 0 │
1 │ 0 │
└ ┘
通过 scipy.sparse.spmatrix
要从 spmatrix 对象构建 sparse.COO
数组,您可以使用 sparse.COO.from_scipy_sparse
方法。例如,如果 x
是一个 scipy.sparse.spmatrix,您可以执行以下操作来获取一个等效的 sparse.COO
数组
s = COO.from_scipy_sparse(x)
通过 [Numpy 数组][numpy.ndarray
]
要从 numpy.ndarray
对象构建 sparse.COO
数组,您可以使用 sparse.COO.from_numpy
方法。例如,如果 x
是一个 numpy.ndarray
,您可以执行以下操作来获取一个等效的 sparse.COO
数组
s = COO.from_numpy(x)
生成随机 sparse.COO
对象
sparse.random
方法可用于创建随机 sparse.COO
数组。例如,以下代码将生成一个 \(10 \times 10\) 矩阵,其中包含 \(10\) 个非零项,每个项都在区间 \([0, 1)\) 内。
s = sparse.random((10, 10), density=0.1)
从 sparse.DOK
数组构建 sparse.COO
数组
如果不容易以简单方式构建 coords
和 data
,则可以从 sparse.DOK
数组构建 sparse.COO
数组。sparse.DOK
数组提供了一个简单的构建器接口来构建 sparse.COO
数组,但目前,它们几乎没有其他功能。
您可以从定义 sparse.DOK
数组的形状(以及可选的数据类型)开始。如果您未指定 dtype,它将从值字典中推断出来,如果不存在,则设置为 dtype('float64')
。
s = DOK((6, 5, 2))
s2 = DOK((2, 3, 4), dtype=np.uint8)
之后,您可以通过将数组或标量分配给原始数组的元素或切片来构建数组。遵循广播规则。
s[1:3, 3:1:-1] = [[6, 5]]
当且仅当所有维度都被索引时,DOK 数组才支持高级索引赋值。
s[[0, 2], [2, 1], [0, 1]] = 5
s[[0, 3], [0, 4], [0, 1]] = [1, 5]
除了索引赋值和检索之外,sparse.DOK
数组还支持任意广播函数,可接受任意数量的参数,这些参数可以是 sparse.SparseArray
对象、scipy.sparse.spmatrix
对象或 numpy.ndarray
。
x = sparse.random((10, 10), 0.5, format="dok")
y = sparse.random((10, 10), 0.5, format="dok")
sparse.elemwise(np.add, x, y)
sparse.DOK
数组还支持标准 ufunc 和运算符(包括比较运算符),可与其他实现 numpy ndarray.__array_ufunc___ 方法的对象结合使用。例如,以下代码将对两个数组执行逐元素相等比较,并返回一个新的布尔型 sparse.DOK
数组。
x = sparse.random((10, 10), 0.5, format="dok")
y = np.random.random((10, 10))
x == y
当且仅当所有 sparse.SparseArray
对象都是 sparse.DOK
数组时,元素级函数和标准 ufunc 才返回 sparse.DOK
数组。否则,将返回 sparse.COO
数组或密集数组。
最后,您可以将 sparse.DOK
数组转换为 sparse.COO
数组。
s3 = COO(s)
此外,可以使用常规 Numpy 索引访问 sparse.DOK
数组的单个元素和切片,当且仅当所有维度都被索引时,也可以使用高级索引。切片和高级索引将始终返回一个新的 DOK 数组。
s[1, 2, 1] # 5
s[5, 1, 1] # 0
s[[0, 3], [0, 4], [0, 1]] # <DOK: shape=(2,), dtype=float64, nnz=2, fill_value=0.0>
将 sparse.COO
对象转换为其他格式
sparse.COO
数组可以通过以下方法转换为 Numpy 数组,或某些 spmatrix 子类:
sparse.COO.todense
:无条件转换为numpy.ndarray
。sparse.COO.maybe_densify
:根据某些约束转换为numpy.ndarray
。sparse.COO.to_scipy_sparse
:如果数组是二维的,则转换为scipy.sparse.coo_matrix
。sparse.COO.tocsr
:如果数组是二维的,则转换为scipy.sparse.csr_matrix
。sparse.COO.tocsc
:如果数组是二维的,则转换为scipy.sparse.csc_matrix
。