对 sparse.COO
和 sparse.GCXS
数组的操作
运算符
sparse.COO
和 sparse.GCXS
对象支持多种操作。它们与标量、sparse.COO
和 sparse.GCXS
对象以及 scipy.sparse.spmatrix 对象交互,所有这些都遵循标准的 Python 和 Numpy 惯例。
例如,以下 Numpy 表达式对于 Numpy 数组、COO 数组或两者的混合都会产生等效结果
np.log(X.dot(beta.T) + 1)
然而,某些操作尚不受支持,例如隐式导致密集结构的操作,或尚未为稀疏数组实现的 numpy 函数。
np.linalg.cholesky(x) # sparse cholesky not implemented
本页描述了这些有效操作及其局限性。
此函数允许您将任意广播函数应用于任意数量的参数,其中参数可以是 sparse.SparseArray
对象或 scipy.sparse.spmatrix
对象。例如,以下操作将添加两个数组
sparse.elemwise(np.add, x, y)
警告
以前,sparse.elemwise
是 sparse.COO
类的一个方法。现在,它已移至 sparse 模块。
自动致密化
导致密集矩阵的操作,例如与 [Numpy 数组][numpy.ndarray
] 的操作会引发 ValueError。例如,如果 x
是 numpy.ndarray
,以下操作将引发 ValueError
x + y
然而,以下所有操作都是有效的。
x + 0
x != y
x + y
x == 5
5 * x
x / 7.3
x != 0
x == 0
~x
x + 5
我们还支持非零填充值的操作。这些操作将零值映射到非零值,例如 x + 1
或 ~x
。在这些情况下,它们将产生一个填充值为 1
或 True
的输出,假设原始数组的填充值分别为 0
或 False
。
如果需要致密化,则必须明确进行。换句话说,您必须在 sparse.SparseArray.todense
对象上调用 sparse.SparseArray
。如果两个操作数都是 sparse.SparseArray
,则两者都必须致密化。
与 NumPy 数组的操作
在某些情况下,也支持与 NumPy 数组的操作。例如,如果 x
是 sparse.COO
且 y
是一个 NumPy 数组,以下操作将起作用
x * y
与 NumPy 数组执行逐元素操作时必须满足以下条件
- 操作必须产生一致的填充值。换句话说,结果数组也必须是稀疏的。
- 对 NumPy 数组进行操作时,在广播数组时不能增加大小。
与 scipy.sparse.spmatrix
的操作
某些与 scipy.sparse.spmatrix
的操作也受支持。例如,如果 y
是一个 scipy.sparse.spmatrix
,则以下所有操作都允许
x + y
x - y
x * y
x > y
x < y
通常,对 scipy.sparse.spmatrix
进行操作与对 sparse.COO
或 sparse.GCXS
进行操作相同,只要它位于运算符的右侧即可。
注意
如果 x
是 scipy.sparse.spmatrix,则结果无法保证。因此,我们建议所有 Scipy 稀疏矩阵在进行任何操作之前都应显式转换为 sparse.COO
或 sparse.GCXS
。
广播
所有二元运算符都支持广播。这意味着(在某些条件下)您可以在形状不等的数组上执行二元操作。即,当形状缺少一个维度,或当一个维度为 1
时。例如,对两个形状分别为 (4,)
和 (5, 1)
的 COO
数组执行二元操作,会产生一个形状为 (5, 4)
的对象。形状为 (1, 4)
和 (5, 1)
的数组也会发生同样的情况。然而,(4, 1)
和 (5, 1)
将引发 ValueError
。如果需要致密化,
逐元素操作
sparse.COO
和 sparse.GCXS
数组支持各种逐元素操作。然而,与运算符一样,将零映射到非零值的操作不受支持。
例如,以下所有操作都是可能的,并且将产生另一个 sparse.SparseArray
np.abs(x)
np.sin(x)
np.sqrt(x)
np.conj(x)
np.expm1(x)
np.log1p(x)
np.exp(x)
np.cos(x)
np.log(x)
如上所示,在最后三种情况下,将生成一个具有非零填充值的数组。
请注意,您可以对任何一元或二元 sparse.COO
数组、numpy.ndarray
对象和标量应用操作,只要结果不是密集的,它就会起作用。当应用于 numpy.ndarray
对象时,我们会检查对数组进行零操作是否总是产生零。
归约
sparse.COO
和 sparse.GCXS
对象支持多种归约。然而,并非所有重要的归约都已实现(欢迎提供帮助!)。以下所有归约目前都有效
x.sum(axis=1)
np.max(x)
np.min(x, axis=(0, 2))
x.prod()
此方法可以接受任意 numpy.ufunc
并使用该方法执行归约。例如,以下操作将执行求和
x.reduce(np.add, axis=1)
注意
此库目前通过将所有坐标沿提供的轴分组并对其进行归约来执行归约。然后,如果组中的数量不足,它会额外进行一次零归约。因此,如果归约可以通过添加多个零而改变,则此方法将不准确。但是,它在大多数情况下都有效。
支持的归约部分列表
虽然任何二元 numpy.ufunc
都应适用于归约,但在以 x.reduction()
形式调用时,支持以下归约
索引
sparse.COO
和 sparse.GCXS
数组可以像常规 numpy.ndarray
对象一样进行索引。它们支持整数、切片和布尔索引。然而,目前,numpy 高级索引尚未完全支持。这意味着以下所有操作都与 Numpy 中的工作方式相同,只是它们将生成 sparse.SparseArray
数组而不是 numpy.ndarray
对象,并在预期位置生成标量。假设 z.shape
是 (5, 6, 7)
z[0]
z[1, 3]
z[1, 4, 3]
z[:3, :2, 3]
z[::-1, 1, 3]
z[-1]
以下所有操作都将引发 IndexError
,就像 Numpy 1.13 及更高版本中一样。
z[6]
z[3, 6]
z[1, 4, 8]
z[-6]
高级索引
支持高级索引(用其他数组对数组进行索引),但仅限于使用单个数组进行索引。目前不支持使用多个数组对单个数组进行索引。如上所述,如果 z.shape
是 (5, 6, 7)
,则以下所有操作都将像 NumPy 一样工作
z[[0, 1, 2]]
z[1, [3]]
z[1, 4, [3, 6]]
z[:3, :2, [1, 5]]
包配置
默认情况下,当执行诸如 np.array(COO)
之类的操作时,我们不允许将数组转换为密集数组,并且它会引发 RuntimeError
。为防止这种情况,请将环境变量 SPARSE_AUTO_DENSIFY
设置为 1
。
如果希望在创建稀疏数组时,如果它占用的内存不小于等效密集数组,则引发警告,请将环境变量 SPARSE_WARN_ON_TOO_DENSE
设置为 1
。
其他操作
sparse.COO
和 sparse.GCXS
数组支持许多其他常见操作。其中包括 sparse.dot
、sparse.tensordot
、sparse.einsum
、sparse.concatenate
和 sparse.stack
、sparse.COO.transpose
和 sparse.COO.reshape
。您可以在API 参考页面上查看完整列表。
注意
某些操作需要零填充值(例如 sparse.COO.nonzero
),而其他操作(例如 sparse.concatenate
)要求所有输入都具有一致的填充值。有关详细信息,请查阅 API 参考。