Skip to main content
v2026.11,858 entries · CC-BY 4.0
LAC HealthMedical & Research SuppliesReagents, PPE & instruments — chain-of-custody documented.Fast, traceable sourcing built for regulated research environments, from bench consumables to instrumentation.Shop lac.us CodeCASRAIlac.us

SciPy Sparse: csr_array, Formats and Sparse Solvers

How to build and convert scipy.sparse arrays, read the CSR layout, choose a storage format, and pick a scipy.sparse.linalg solver.

Written and maintained by CASRAI Editorial Board

Last updated

SciPy’s scipy.sparse package stores matrices in which most entries are zero by keeping only the non-zero values and their positions. The current documentation says SciPy sparse “is shifting from a sparse matrix interface to a sparse array interface” and that the project expects “to deprecate the sparse matrix interface” in the next few releases, so new code should use classes such as csr_array rather than csr_matrix. This guide builds one array three ways, shows how to read its internal arrays, and maps each storage format and solver to the condition the documentation attaches to it.

What it is used for in research

Sparse storage suits data where each row touches only a few columns: a document-by-term count table, a graph adjacency matrix, or the coefficient matrix of a discretised physical model. Instead of holding every zero, a sparse array holds the non-zero entries only, and scipy.sparse.linalg offers solvers and decompositions that work on that representation. A dense NumPy array remains the better choice when most entries are non-zero; see the NumPy matrix multiplication guide and the numpy.linalg.norm guide for the dense counterparts. Sparse matrices also appear in machine-learning pipelines, for example when text features are passed to a model, as in the train/test split guide.

Install or access

The SciPy project’s install page (scipy.org/install, checked 2026-10-29) gives python -m pip install scipy, after first creating a virtual environment. For conda users it names Miniforge as the recommended way to install conda and mamba, followed by conda install scipy (conda-forge) or mamba install scipy. Sparse support ships inside SciPy; there is nothing separate to install.

Step-by-step: build, convert and solve

1. Build in COO format

The SciPy sparse reference says COO “is recommended” for construction, and that duplicate (i, j) entries are summed when converting to CSR or CSC. Indices do not need to be sorted.

import numpy as np
from scipy import sparse

row  = [0, 0, 1, 2, 2, 2]
col  = [0, 2, 2, 0, 1, 2]
data = [1, 2, 3, 4, 5, 6]
A = sparse.coo_array((data, (row, col)), shape=(3, 3))

2. Convert to CSR for arithmetic

The reference states that conversions among CSR, CSC and COO “are efficient, linear-time operations”, and that CSR is “especially suitable for fast matrix vector products”.

S = A.tocsr()          # or build directly: sparse.csr_array((data, (row, col)), shape=(3, 3))
y = S @ np.array([1, 1, 1])

3. Solve a sparse linear system

scipy.sparse.linalg.spsolve solves Ax = b, where b may be a vector or a matrix.

from scipy.sparse.linalg import spsolve

M = sparse.csr_array(([4, 1, 1, 3], ([0, 0, 1, 1], [0, 1, 0, 1])), shape=(2, 2))
x = spsolve(M, np.array([1, 2]))

Output and how to read it

Call .toarray() to see a sparse array as a dense NumPy array. For the example above, S.toarray() returns [[1,0,2],[0,0,3],[4,5,6]], matching the worked example in the csr_array reference. The same array can be written in CSR’s own layout: indptr = [0, 2, 3, 6] and indices = [0, 2, 2, 0, 1, 2], because “column indices for row i are stored in indices[indptr[i]:indptr[i+1]]“. Row 0 therefore owns indices[0:2] = columns 0 and 2, row 1 owns indices[2:3] = column 2, and row 2 owns indices[3:6] = columns 0, 1 and 2. Here S @ [1, 1, 1] gives the row sums [3, 3, 15], and spsolve(M, [1, 2]) returns approximately [0.0909, 0.6364], which is 1/11 and 7/11: check that 4(1/11) + 7/11 = 1 and 1/11 + 3(7/11) = 2.

Duplicates are summed, not overwritten. With row=[0,1,2,0], col=[0,1,1,0] and data=[1,2,4,8], the two entries at (0, 0) combine into 9, and the result is [[9,0,0],[0,2,0],[0,4,0]].

Which format to use

The table below restates the format notes in the SciPy documentation.

Format Class What the documentation says
COO coo_array “A sparse array in COOrdinate format”; recommended for construction.
CSR csr_array Efficient CSR + CSR and CSR * CSR arithmetic, efficient row slicing, fast matrix-vector products. Column slicing is slow (consider CSC); changes to the sparsity structure are expensive (consider LIL or DOK).
CSC csc_array “Compressed Sparse Column array”; the suggested alternative to CSR when column slicing matters.
LIL lil_array “Row-based LIst of Lists sparse array”; suggested when the sparsity structure changes.
DOK dok_array “Dictionary Of Keys based sparse array”; suggested when the sparsity structure changes.
DIA dia_array “Sparse array with DIAgonal storage.”
BSR bsr_array “Block Sparse Row format sparse array.”

Solvers and decompositions in scipy.sparse.linalg

Function Documented purpose
spsolve Solve the sparse linear system Ax = b; b may be a vector or a matrix.
splu LU decomposition of a sparse, square matrix.
cg Conjugate Gradient method for Ax = b, for a symmetric, positive-definite A.
gmres Generalized Minimal RESidual method for Ax = b.
eigs k eigenvalues and eigenvectors of a square matrix.
eigsh The eigenvalue routine for real symmetric or complex Hermitian matrices.
svds Partial singular value decomposition of a sparse matrix.
norm Norm of a sparse matrix.

The only condition the documentation places on cg is symmetric, positive-definite A, so check that property of your matrix before choosing it over gmres.

Troubleshooting

Column slicing is slow

CSR makes row slicing efficient and column slicing slow. If your workload slices columns, convert with .tocsc(); the conversion is linear-time.

Changing the structure of a CSR array is slow

The csr_array reference lists structural changes as expensive and points to LIL or DOK. Build or edit in one of those, then convert to CSR for arithmetic.

Entries are larger than expected

Duplicate (i, j) entries are summed when converting to CSR or CSC. If your input repeats coordinates, the result adds them, as in the 9 example above.

Code uses csr_matrix

The matrix interface is the one the documentation expects to deprecate. Moving to the array classes (csr_array, coo_array) is the forward-compatible choice. Related SciPy topics: scipy.optimize, scipy.interpolate and scipy.signal.

Free alternatives

Option What its documentation says
NumPy dense arrays The standard dense array that .toarray() returns; store every entry, zeros included.
pydata sparse package Implements sparse arrays of arbitrary dimension on top of numpy and scipy.sparse. sparse.COO and sparse.DOK generalize the scipy.sparse COO and DOK layouts, and sparse.GCXS extends compressed sparse storage beyond two dimensions (sparse.pydata.org, checked 2026-10-29).

FAQ

What does scipy.sparse do?

It provides sparse array classes in seven formats and a sparse.linalg module of solvers and decompositions that operate on them.

Should I use csr_array or csr_matrix?

Use csr_array. The SciPy documentation says the project is shifting to the array interface and expects to deprecate the matrix interface.

Which format should I build a sparse array in?

COO, which the documentation recommends for construction, then convert to CSR or CSC for arithmetic.

How do I convert a sparse array to a dense one?

Call .toarray().

Sources

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about SciPy Sparse: csr_array, Formats and Sparse Solvers

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →