在Julia中基于(obj,obj,距离/相似度)三元组生成成对距离矩阵
优化方案
你原来的实现效率低的核心问题是嵌套循环中每次都对整个r矩阵做布尔索引查找,时间复杂度为O(N²*M)(N为唯一对象数,M为三元组行数),数据量稍大就会有明显的性能瓶颈。可以通过一次遍历+索引映射的方式把时间复杂度降到O(M+N²),性能能提升几个数量级。
实现1:单循环索引赋值
using NamedArrays function DistanceMatrixFromTriColumn(r::AbstractArray) # 生成名称到整数索引的映射,避免重复查找 names = unique(vcat(r[:, 1], r[:, 2])) name2idx = Dict(name => i for (i, name) in enumerate(names)) n = length(names) dist = NamedArray(zeros(n, n), (names, names)) # 仅遍历一次三元组完成赋值,无需重复扫描全矩阵 for i in 1:size(r, 1) row_idx = name2idx[r[i, 1]] col_idx = name2idx[r[i, 2]] dist[row_idx, col_idx] = r[i, 3] end return dist end
实现2:向量化索引赋值(更接近R语言的操作风格)
如果你习惯R语言的向量化操作风格,可以用笛卡尔索引直接批量赋值,完全避免显式循环:
using NamedArrays function DistanceMatrixFromTriColumn(r::AbstractArray) names = unique(vcat(r[:, 1], r[:, 2])) name2idx = Dict(name => i for (i, name) in enumerate(names)) n = length(names) dist_mat = zeros(n, n) # 批量生成坐标,一次性赋值 rows = [name2idx[v] for v in r[:, 1]] cols = [name2idx[v] for v in r[:, 2]] dist_mat[CartesianIndex.(rows, cols)] = r[:, 3] return NamedArray(dist_mat, (names, names)) end
两种实现的输出和你原来的代码完全一致,在数据量较大时(比如10万级以上三元组),性能提升可达数十到上百倍。
内容的提问来源于stack exchange,提问作者status_five
相关产品推荐
相关产品推荐

