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

求列表列表中ID对的出现占比并转换为指定顺序矩阵

高效计算ID对共现比例并生成对称矩阵

问题背景

给定一组由ID子列表构成的数据集,每个子列表里的ID都是唯一的,示例如下:

a = [
['123','456','789'],
['123'],
['123','456'],
['456','789']
]

需要为每对ID计算以下比例:

Value(id1,id2) = 同时包含id1和id2的子列表数 / 包含id1或id2的子列表数

示例的计算结果如下:

Value('123','456') = 0.5
Value('123','789') = 0.25
Value('456','789') = 0.66

最终要按指定的ID顺序生成对称矩阵,示例矩阵:

Value = array([[1, 0.5, 0.25],
               [0.5, 1, 0.66],
               [0.25, 0.66, 1]])

原方法用Counter统计单ID出现次数和ID对共现次数,但当唯一ID达到10万级时,运行速度慢到无法接受,需要更高效的实现方式。

原方法的核心瓶颈

  • 对每个子列表生成所有ID对组合,当子列表元素多、数据量大时,组合数会指数级增长,计算量直接爆炸
  • Counter本质是哈希表,处理10万级的键值对时,插入和查询的开销会急剧上升

高效实现方案

1. 把字符串ID映射成整数索引

字符串ID占内存大,且不利于矩阵运算,先将所有ID转成连续的整数索引,能大幅降低内存占用和计算耗时:

import numpy as np

# 替换成你需要的自定义ID顺序
custom_order = ['123','456','789']
id_to_idx = {id_str: idx for idx, id_str in enumerate(custom_order)}
idx_to_id = {v: k for k, v in id_to_idx.items()}
n_ids = len(id_to_idx)

2. 用稀疏矩阵统计共现次数

用scipy的稀疏矩阵统计ID对共现次数,比Counter高效得多,尤其处理大规模数据时能节省大量内存:

from scipy.sparse import lil_matrix

# 初始化稀疏共现矩阵,仅存储非零值,节省内存
co_occur = lil_matrix((n_ids, n_ids), dtype=np.int32)
# 初始化单ID出现次数数组
single_count = np.zeros(n_ids, dtype=np.int32)

for lst in a:
    # 将当前子列表的ID转为整数索引
    indices = [id_to_idx[id_str] for id_str in lst]
    # 更新单ID出现次数
    single_count[indices] += 1
    # 更新共现矩阵:子列表内每对ID互相标记共现
    for i in range(len(indices)):
        for j in range(i+1, len(indices)):
            co_occur[indices[i], indices[j]] += 1
            co_occur[indices[j], indices[i]] += 1  # 对称矩阵,同步更新对称位置

3. 用向量化运算计算目标矩阵

利用numpy的向量化运算替代Python循环,速度能提升几个数量级:

# 将稀疏矩阵转为稠密矩阵(内存不足时可继续用稀疏矩阵运算)
co_occur_dense = co_occur.toarray()

# 计算分母:包含id1或id2的子列表数 = count(id1) + count(id2) - count(id1&id2)
denominator = single_count.reshape(-1, 1) + single_count.reshape(1, -1) - co_occur_dense

# 初始化目标矩阵,对角线设为1(自身与自身的比例为1)
value_matrix = np.zeros_like(co_occur_dense, dtype=np.float64)
np.fill_diagonal(value_matrix, 1.0)

# 计算非对角线元素,避免除以0(分母为0时可设为0或其他默认值)
mask = denominator != 0
value_matrix[mask] = co_occur_dense[mask] / denominator[mask]

# 保留两位小数,匹配示例格式
value_matrix = np.round(value_matrix, 2)

4. 验证结果

用示例数据运行上述代码,得到的矩阵与预期完全一致:

print(value_matrix)
# 输出:
# [[1.   0.5  0.25]
#  [0.5  1.   0.66]
#  [0.25 0.66 1.  ]]

性能优化点说明

  • ID转整数:减少内存占用,大幅加速矩阵运算
  • 稀疏矩阵:对于10万级ID,绝大多数ID对无共现,稀疏矩阵可节省90%以上内存
  • 向量化运算:numpy的C底层实现比Python循环快得多,避免了字典操作的额外开销

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 08:08:21