跳到内容

构造稀疏数组

通过坐标和数据

您可以从坐标和值数据构建 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  
                      

您可以(也应该)为 coordsdata 传入 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 数组

如果不容易以简单方式构建 coordsdata,则可以从 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 子类: