Sparse n-dimensional arrays for the PyData ecosystem with multiple backend implementations
npx @tessl/cli install tessl/pypi-sparse@0.17.0A comprehensive sparse n-dimensional array library for the PyData ecosystem that provides efficient storage and computation for arrays with many zero elements. The library features multiple backend implementations (Numba, Finch, MLIR) for optimal performance across different computational scenarios and supports the Array API standard for seamless interoperability with NumPy and other array libraries.
pip install sparsepip install sparse[finch] or pip install sparse[mlir]import sparseCommon imports for working with sparse arrays:
from sparse import COO, DOK, GCXS
import sparseimport sparse
import numpy as np
# Create a sparse COO array from dense data
dense_array = np.array([[1, 0, 2], [0, 0, 3], [4, 0, 0]])
sparse_array = sparse.COO.from_numpy(dense_array)
# Create sparse arrays directly
coords = [[0, 1, 2], [0, 2, 0]] # row, col indices
data = [1, 3, 4] # values at those positions
shape = (3, 3)
coo_array = sparse.COO(coords, data, shape)
# Perform operations
result = sparse_array + coo_array
dense_result = result.todense()
# Mathematical operations work like NumPy
sum_result = sparse.sum(sparse_array, axis=0)
dot_product = sparse.dot(sparse_array, sparse_array.T)
print(f"Original array shape: {sparse_array.shape}")
print(f"Number of stored elements: {sparse_array.nnz}")
print(f"Density: {sparse_array.density:.2%}")The sparse library uses a multi-backend architecture for optimal performance:
SPARSE_BACKEND environment variable
The main sparse array types providing different storage strategies and performance characteristics for various sparse data patterns.
class SparseArray:
"""Abstract base class for all sparse arrays"""
def __init__(self, shape, fill_value=None): ...
@property
def nnz(self): ...
@property
def ndim(self): ...
@property
def size(self): ...
@property
def density(self): ...
@property
def T(self): ...
@property
def real(self): ...
@property
def imag(self): ...
def todense(self): ...
def astype(self, dtype, casting="unsafe", copy=True): ...
class COO(SparseArray):
"""Coordinate format sparse array - main user-facing class"""
def __init__(self, coords, data=None, shape=None, has_duplicates=True, sorted=False, prune=False, cache=False, fill_value=None, idx_dtype=None): ...
@classmethod
def from_numpy(cls, x, fill_value=None, idx_dtype=None): ...
@classmethod
def from_scipy_sparse(cls, x, /, *, fill_value=None): ...
@property
def T(self): ...
@property
def mT(self): ...
def todense(self): ...
def copy(self, deep=True): ...
def transpose(self, axes=None): ...
def dot(self, other): ...
def tocsr(self): ...
def tocsc(self): ...
class DOK(SparseArray):
"""Dictionary of Keys format - efficient for construction"""
def __init__(self, shape, data=None, dtype=None, fill_value=None): ...
@classmethod
def from_scipy_sparse(cls, x, /, *, fill_value=None): ...
@classmethod
def from_coo(cls, x): ...
@classmethod
def from_numpy(cls, x): ...
def to_coo(self): ...
def __getitem__(self, key): ...
def __setitem__(self, key, value): ...
class GCXS(SparseArray):
"""Generalized Compressed Sparse format (CSR/CSC)"""
def __init__(self, arg, shape=None, compressed_axes=None, prune=False, fill_value=None, idx_dtype=None): ...
@classmethod
def from_numpy(cls, x, compressed_axes=None, fill_value=None, idx_dtype=None): ...
@classmethod
def from_coo(cls, x, compressed_axes=None, idx_dtype=None): ...
@classmethod
def from_scipy_sparse(cls, x, /, *, fill_value=None): ...
@property
def T(self): ...
@property
def mT(self): ...
def tocoo(self): ...
def todok(self): ...
def change_compressed_axes(self, new_compressed_axes): ...Functions for creating sparse arrays from various inputs, including conversion from dense arrays, construction of special matrices, and generation of empty arrays.
def asarray(obj, /, *, dtype=None, format="coo", copy=False, device=None): ...
def zeros(shape, dtype=float, format="coo", *, device=None, **kwargs): ...
def ones(shape, dtype=float, format="coo", *, device=None, **kwargs): ...
def eye(N, M=None, k=0, dtype=float, format="coo", *, device=None, **kwargs): ...
def full(shape, fill_value, dtype=None, format="coo", order="C", *, device=None, **kwargs): ...
def empty(shape, dtype=float, format="coo", *, device=None, **kwargs): ...
def random(shape, density=None, nnz=None, random_state=None, data_rvs=None, format="coo", fill_value=None, idx_dtype=None, **kwargs): ...
def zeros_like(a, dtype=None, shape=None, format=None, *, device=None, **kwargs): ...
def ones_like(a, dtype=None, shape=None, format=None, *, device=None, **kwargs): ...
def full_like(a, fill_value, dtype=None, shape=None, format=None, *, device=None, **kwargs): ...
def empty_like(a, dtype=None, shape=None, format=None, *, device=None, **kwargs): ...Comprehensive mathematical functions including arithmetic, trigonometric, exponential, and comparison operations that preserve sparsity when possible.
# Arithmetic operations
def add(x1, x2): ...
def subtract(x1, x2): ...
def multiply(x1, x2): ...
def divide(x1, x2): ...
def pow(x1, x2): ...
# Trigonometric functions
def sin(x): ...
def cos(x): ...
def tan(x): ...
def exp(x): ...
def log(x): ...
def sqrt(x): ...Matrix operations including dot products, matrix multiplication, eigenvalue computations, and other linear algebra functions optimized for sparse matrices.
def dot(a, b): ...
def matmul(x1, x2): ...
def outer(a, b): ...
def kron(a, b): ...
def tensordot(a, b, axes=2): ...
def einsum(subscripts, *operands): ...Functions for reshaping, indexing, slicing, and reorganizing sparse arrays while maintaining sparsity structure efficiently.
def reshape(a, shape): ...
def transpose(a, axes=None): ...
def moveaxis(a, source, destination): ...
def squeeze(a, axis=None): ...
def expand_dims(a, axis): ...
def concatenate(arrays, axis=0): ...
def stack(arrays, axis=0): ...Functions for computing statistics and aggregations along specified axes, including standard reductions and NaN-aware variants.
def sum(a, axis=None, keepdims=False): ...
def mean(a, axis=None, keepdims=False): ...
def max(a, axis=None, keepdims=False): ...
def min(a, axis=None, keepdims=False): ...
def var(a, axis=None, keepdims=False): ...
def std(a, axis=None, keepdims=False): ...
def nansum(a, axis=None, keepdims=False): ...Functions for saving, loading, and converting sparse arrays between different formats and libraries.
def save_npz(file, *args, **kwargs): ...
def load_npz(file): ...
def asnumpy(a): ...Sparse supports all NumPy data types and provides type conversion utilities:
# Integer types
int8, int16, int32, int64
uint8, uint16, uint32, uint64
# Floating point types
float16, float32, float64
# Complex types
complex64, complex128
# Boolean type
bool
# Type utilities
def astype(a, dtype): ...
def can_cast(from_, to): ...
def result_type(*arrays_and_dtypes): ...import os
# Set backend before importing sparse
os.environ['SPARSE_BACKEND'] = 'Numba' # Default
# os.environ['SPARSE_BACKEND'] = 'Finch' # Requires sparse[finch]
# os.environ['SPARSE_BACKEND'] = 'MLIR' # Requires sparse[mlir]
import sparseimport sparse
print(sparse.__version__) # Version string
print(sparse.__version_tuple__) # Version tuple
print(sparse.__array_api_version__) # Array API version