Sparse Matrix

9 functions for sparse matrices in CSC (Compressed Sparse Column) format. Essential for single-cell RNA-seq count matrices where >90% of values are zero.

sparse_matrix

Create a sparse matrix from dimensions and COO entry records.

sparse_matrix(nrows, ncols, entries) -> SparseMatrix
ParameterTypeDescription
entriesList<Record>Records with row, col, and val fields
nrowsintNumber of rows
ncolsintNumber of columns
# 30,000 genes x 10,000 cells, mostly zeros
let entries = [
  {row: 0, col: 5, val: 3.0},     # gene 0, cell 5 = 3 counts
  {row: 0, col: 12, val: 1.0},    # gene 0, cell 12 = 1 count
  {row: 142, col: 5, val: 7.0},   # gene 142, cell 5 = 7 counts
]
let mat = sparse_matrix(30000, 10000, entries)

to_dense / to_sparse

Convert between sparse and dense matrix representations.

to_dense(sparse) -> matrix
to_sparse(matrix) -> sparse
let small_sparse = sparse_matrix(3, 3, [
  {row: 0, col: 0, val: 1.0},
  {row: 1, col: 2, val: 2.0},
  {row: 2, col: 1, val: 3.0}
])
let dense = to_dense(small_sparse)
let sp = to_sparse(dense)
println(nnz(sp))   # 3

Edge case: to_dense on a large scRNA-seq matrix (30k x 10k) allocates ~2.4 GB. Use sparse operations when possible.

nnz

Count of non-zero entries in the sparse matrix.

nnz(sparse) -> int
let mat = sparse_matrix(10, 10, [
  {row: 0, col: 0, val: 5.0},
  {row: 1, col: 2, val: 3.0},
])
nnz(mat)   # 2

# Sparsity ratio
let sparsity = 1.0 - float(nnz(mat)) / float(10 * 10)
println("Sparsity:", round(sparsity * 100, 1), "%")   # Sparsity: 98.0%

sparse_get

Get a single value from a sparse matrix by row and column index.

sparse_get(sparse, row, col) -> float
let mat = sparse_matrix(10, 10, [
  {row: 0, col: 0, val: 5.0},
  {row: 1, col: 2, val: 3.0},
])
sparse_get(mat, 0, 0)   # 5.0
sparse_get(mat, 0, 1)   # 0.0  (not stored = zero)

normalize_sparse

Normalize columns (cells) to sum to a target value, commonly 10,000 for CPM-like normalization.

normalize_sparse(mat, method) -> SparseMatrix
let raw_counts = sparse_matrix(30000, 10000, entries)
let normalized = normalize_sparse(raw_counts, "log1p_cpm")

sparse_row_sums / sparse_col_sums

Compute row or column sums of a sparse matrix efficiently.

sparse_row_sums(sparse) -> list
sparse_col_sums(sparse) -> list
let mat = sparse_matrix(3, 3, [
  {row: 0, col: 0, val: 5.0},
  {row: 0, col: 1, val: 3.0},
  {row: 1, col: 0, val: 2.0},
])
sparse_row_sums(mat)   # [8.0, 2.0, 0.0]
sparse_col_sums(mat)   # [7.0, 3.0, 0.0]