numpy本身不支持稀疏矩阵,因其设计为稠密数组,会为所有元素(含大量零)分配内存;必须使用scipy.sparse(如coo、csr、csc等格式)实现高效存储与计算,且转换和操作需谨慎避免隐式转稠密。

NumPy 本身不支持稀疏矩阵——直接调用 numpy.array 或 numpy.matrix 加载大规模稀疏数据,会立刻吃光内存。真要处理稀疏结构,必须切换到 scipy.sparse,并谨慎选择格式和转换路径。
为什么不能直接用 NumPy 创建稀疏矩阵
NumPy 的核心是稠密数组,所有元素都占内存。哪怕你只存 100 个非零值,用 np.zeros((10000, 10000)) 就已分配约 800MB 内存(float64)。这不是“效率低”,而是根本不符合稀疏场景的设计前提。
-
np.array没有跳过零值的存储机制 - 没有内置的稀疏索引、压缩行/列等结构支持
-
scipy.sparse中的各类格式(如csr_matrix、csc_matrix)才是专为稀疏设计的底层实现
如何从坐标列表(COO)安全转成 CSR/CSC 格式
最常见输入是三元组:行索引、列索引、值(比如来自文件或计算结果)。直接喂给 scipy.sparse.coo_matrix,再转 csr_matrix,是最稳妥的起点。
- 避免直接用
coo_matrix((data, (row, col)), shape=...)后立刻调用.tocsr()—— 如果row/col未排序或含重复项,tocsr()内部会自动去重求和,但不报错,容易掩盖数据问题 - 显式检查重复:用
np.unique(np.column_stack([row, col]), axis=0, return_index=True)看是否有多余索引 - 若需保留原始重复项语义(如累加),应先用
scipy.sparse.coo_matrix构造,它默认合并;若需保留,得自己聚合data数组
示例:
from scipy import sparse import numpy as np <p>row = np.array([0, 1, 2, 0]) col = np.array([0, 1, 2, 2]) data = np.array([1, 2, 3, 4]) # (0,2) 出现两次 → 值会相加为 7</p><p>coo = sparse.coo_matrix((data, (row, col)), shape=(3, 3)) csr = coo.tocsr() # 自动压缩、排序、去重求和</p>
保存稀疏矩阵时该选 .npz 还是 .mtx?
别用 np.save 或 pickle——它们会把 csr_matrix 当普通对象序列化,失去格式优势,且跨 Python 版本可能失效。优先选两种方案:
-
scipy.io.mmwrite+mmread:输出 Matrix Market 格式(.mtx),纯文本可读,通用性强,适合调试或跨语言交换 -
np.savez_compressed存 CSR 的三个核心数组:.data、.indices、.indptr,加载时手动重建:sparse.csr_matrix((data, indices, indptr), shape=...),体积小、速度快,适合 Python 内部流转 - 避免
np.savez(不压缩)——稀疏矩阵的.data数组虽小,但.indptr长度是n_rows+1,大矩阵下也显著,不压缩浪费 IO
CSR 和 CSC 在什么操作下会意外变稠密
看似无害的操作可能触发隐式转换:一旦调用 .toarray()、.A、np.array(sparse_mat),就全量展开为 np.ndarray,内存爆炸风险立即生效。
- 布尔索引如
mat[mat > 0.5]返回的是np.ndarray,不是稀疏子集 -
mat + dense_array会广播成稠密结果(除非dense_array是标量或形状严格匹配且为 0) - 乘法中混用
np.dot(mat, dense_vec)安全,但mat @ dense_mat.T若dense_mat太大,中间结果可能撑爆内存
真正需要切片时,优先用 mat[i:j, k:l](返回同格式稀疏子矩阵),而不是先转稠密再切。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











