SciPy CSR vs CSC: Sparse Matrix Storage Differences

This article provides a comparison of the Compressed Sparse Row (CSR) and Compressed Sparse Column (CSC) matrix storage formats in Python's SciPy library. While both formats drastically reduce memory consumption by storing only non-zero elements, their internal structures prioritize different memory layouts. Below, we break down how each format organizes data internally, the structural differences in their index pointer arrays, and how their memory arrangements impact operational efficiency.

The Three-Array System

Both scipy.sparse.csr_matrix and scipy.sparse.csc_matrix store sparse data using three one-dimensional NumPy arrays:

  1. data: Contains the actual non-zero values of the matrix.
  2. indices: Contains the coordinate indices for each element in data.
  3. indptr: Contains pointers indicating where each row or column starts and ends within data and indices.

The key difference between CSR and CSC is how these three arrays represent rows versus columns.

Compressed Sparse Row (CSR) Storage

CSR organizes data along rows (row-major order). It traverses the matrix left-to-right, top-to-bottom.

CSR Example

For the following \(3 \times 3\) matrix:

[[1, 0, 2],
 [0, 0, 3],
 [4, 5, 0]]

The CSR arrays are:

Compressed Sparse Column (CSC) Storage

CSC organizes data along columns (column-major order). It traverses the matrix top-to-bottom, left-to-right.

CSC Example

For the same \(3 \times 3\) matrix:

[[1, 0, 2],
 [0, 0, 3],
 [4, 5, 0]]

The CSC arrays are:

Key Storage and Performance Trade-Offs

1. Memory Footprint Variation

The total memory of both formats is primarily determined by \(2 \times NNZ\) (for data and indices). However, the size of indptr varies:

For non-square matrices, CSR is slightly more memory-efficient when n_rows < n_cols, while CSC is more memory-efficient when n_cols < n_rows.

2. Slicing and Access Patterns

3. Arithmetic Operations