如何使用scipy.sparse.coo_matrix从pandas两列整数数据构造对称0-1稀疏矩阵
使用scipy.coo_matrix从双列pandas DataFrame构造对称二值稀疏矩阵
最终要生成符合以下规则的矩阵:
- 行、列索引完全一致,覆盖从0到DataFrame内所有元素最大值的全部整数
- 只要DataFrame中存在
[i,j]或[j,i]的配对记录,矩阵(i,j)位置的元素就为1,全矩阵最大值不超过1 - 全程使用
scipy.sparse.coo_matrix((data, (row_ind, col_ind)))的构造逻辑实现
现有实现的核心问题
你当前写出的代码:
scipy.sparse.coo_matrix((np.ones_like(df['a']), (df['a'].array, df['b'].array))).toarray()
存在三个不符合要求的缺陷:
- 不满足对称性:仅按DataFrame原始行的顺序赋值(i,j)位置,没有为反向的(j,i)位置同步赋值,矩阵左右不对称
- 重复配对会导致元素值大于1:coo构造器会自动将相同(row, col)位置的传入值累加,若DataFrame中出现重复的配对记录,最终对应位置的数值会大于1
- 矩阵维度不匹配:你之前输出的4行5列结果,本质是没有手动指定矩阵shape,coo默认会分别取行索引的最大值+1、列索引的最大值+1作为矩阵边界,没法保证行列长度一致。
分步实现方案
整个流程完全贴合coo矩阵的构造逻辑,不需要额外的复杂操作:
- 确定统一矩阵形状
计算DataFrame内所有元素的全局最大值max_val = df.to_numpy().max(),最终矩阵的形状为(max_val+1, max_val+1)——因为索引从0开始计数,所以最大值需要加1,保证行、列维度完全一致。 - 拼接正反坐标实现对称
把原DataFrame的两列顺序交换,和原始列拼接成两组坐标:- 原坐标对:行索引取df的a列,列索引取df的b列
- 反向坐标对:行索引取df的b列,列索引取df的a列
将两组行索引、列索引分别拼接,覆盖所有需要赋值1的对称位置。
- 传入构造器完成初始化
给所有拼接后的坐标对应统一的data值1,传入coo构造器,手动指定之前计算好的统一shape。 - 二值化处理
coo矩阵初始化时会自动累加同坐标的传入值,只需将构造好的coo矩阵转成高效的csr格式,把所有非零位置的data值全部覆盖为1,即可保证矩阵最大值为1。
完整可运行代码
import numpy as np import pandas as pd import scipy.sparse as sp # 按示例定义测试用DataFrame df = pd.DataFrame(np.random.randint(5, size=(10,2))) df.columns = ['a', 'b'] # 计算全局最大值,确定统一矩阵形状 max_val = df.to_numpy().max() mat_shape = (max_val + 1, max_val + 1) # 拼接正向、反向坐标对 row_ind = np.concatenate([df['a'].to_numpy(), df['b'].to_numpy()]) col_ind = np.concatenate([df['b'].to_numpy(), df['a'].to_numpy()]) data = np.ones(len(row_ind), dtype=np.int8) # coo构造器初始化 adj_coo = sp.coo_matrix((data, (row_ind, col_ind)), shape=mat_shape) # 二值化处理,保证所有非零值为1 adj_csr = adj_coo.tocsr() adj_csr.data = np.ones_like(adj_csr.data) # 查看最终矩阵 print(adj_csr.toarray())
关键使用提示
- 手动指定shape是使用coo构造器的核心注意点:如果不传入shape参数,coo会分别根据传入的行索引、列索引的最大值自动计算矩阵边界,很容易出现行列长度不一致的问题
- 不需要提前对坐标对做去重操作:coo的设计逻辑本身就支持同坐标多次传入,初始化时自动累加,后续统一覆盖为1即可,操作效率更高
- 正反坐标拼接的方式没有额外计算开销,完全匹配coo“传入坐标列表、对应数值列表、指定形状”的使用逻辑,不需要写循环判断逻辑
内容的提问来源于stack exchange,提问作者aheHkartA
相关产品推荐
相关产品推荐

