You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python Scipy稀疏COO矩阵中保留显式零值并获取其索引

COO矩阵中获取显式零值索引的方法

问题描述

创建了一个COO矩阵,其data数组中包含显式零值。查询data数组能看到这些零值,但调用nonzero()方法时,这些零值的索引会被过滤掉。如何获取这些显式零值的索引?这是否是COO实现的bug?

复现代码如下,最终断言会失败,因为显式元素数量为7,但nonzero()返回的索引仅6个:

import scipy.sparse as sp

sparse_simple = sp.coo_matrix(
    [
        [1.1, 0, 1.1],
        [0, 1.1, 4.1],
        [1.1, 4.1, 1.1]
    ]
)

sparse_simple_data = sparse_simple.data
sparse_simple_nz = sparse_simple.nonzero()
sparse_simple_data[1] = 0
(n_rows, n_cols) = sparse_simple.shape
sparse_simple_with_explicit_close_to_zero = sp.coo_matrix(
    (sparse_simple_data, (sparse_simple_nz[0], sparse_simple_nz[1])),
    shape=(n_rows, n_cols)
)
num_explicit_vals = len(sparse_simple_with_explicit_close_to_zero.data)
nz_idcs = sparse_simple_with_explicit_close_to_zero.nonzero()
num_nzs = len(nz_idcs[0])

assert num_explicit_vals == num_nzs

当前有个临时hack方案:给data数组所有值加极小数值,但不认可这种方法,希望找到正规解决方案。

解答

这不是bug

Scipy稀疏矩阵的设计初衷是通过仅存储非零元素来节省空间,因此nonzero()、count_nonzero()等方法会自动过滤掉显式存储的零值,这是预期行为,并非实现bug。

正规解决方案

COO矩阵的核心结构由三个数组组成:row(所有显式元素的行索引)、col(所有显式元素的列索引)、data(对应元素的值)。这三个数组的长度完全一致,且row和col不会过滤零值,直接利用这两个属性即可获取所有显式元素的索引:

  1. 获取所有显式元素的索引(包括零值)
# 获取所有显式元素的行、列索引
all_row_indices = sparse_simple_with_explicit_close_to_zero.row
all_col_indices = sparse_simple_with_explicit_close_to_zero.col

# 验证长度与data一致
assert len(all_row_indices) == len(sparse_simple_with_explicit_close_to_zero.data)
  1. 单独筛选显式零值的索引
    通过布尔索引过滤data数组,即可提取出零值对应的行、列索引:
# 创建零值掩码
zero_mask = sparse_simple_with_explicit_close_to_zero.data == 0

# 获取显式零值的行、列索引
zero_row_indices = sparse_simple_with_explicit_close_to_zero.row[zero_mask]
zero_col_indices = sparse_simple_with_explicit_close_to_zero.col[zero_mask]

这种方法无需修改矩阵的实际值,完全符合COO矩阵的设计规范,是替代hack方案的正规做法。

内容的提问来源于stack exchange,提问作者JStrahl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 15:00:58