r - 从三元组(obj,obj,距离/相似性)在 Julia 中创建成对距离矩阵
问题描述
我有一个“obj obj distance”形式的矩阵,一个玩具矩阵看起来像这样:
r = [[1,1,1,2,2,2,3,3,3] [1,2,3,1,2,3,1,2,3] [0,.5,.75,.75,0,.25,.5,.25,0]]
我目前有一个解决方案:
using NamedArrays
function DistanceMatrixFromTriColumn(r::AbstractArray)
Names = unique(vcat(r[:,1],r[:,2]))
Dist = NamedArray(zeros(length(Names),length(Names)),(Names,Names))
for row in Names
for col in Names
Dist[row,col] = r[(r[:,1] .== row) .& (r[:,2] .== col),:3][1]
end
end
return Dist
end
DistanceMatrixFromTriColumn(r)
这实际上只是一个嵌套的 for 循环,它穿过第一列,然后穿过第二列。它输出如下内容:
3×3 Named Matrix{Float64}
A ╲ B │ 1.0 2.0 3.0
──────┼─────────────────
1.0 │ 0.0 0.5 0.75
2.0 │ 0.75 0.0 0.25
但是我认为有一种更快的方法,应该有一种方法可以使用索引来做类似的事情,不是吗?我想我记得曾经有人在 R 中做过类似的解决方案。
解决方案
对于您发布的对象被可靠编号的情况,您可以使用类似的方法来加快速度
function distancematrixfromtricolumn(r::AbstractArray)
names = unique(view(r,:,1))
dist = NamedArray(zeros(length(names),length(names)),(names,names))
for i = 1:size(r,1)
row = Int(r[i,1])
col = Int(r[i,2])
dist[row,col] = r[i,3]
end
return dist
end
您可能还会注意到一些风格上的变化:我将一些名称转换为小写,以遵循 Julia 约定,即函数和变量是小写,而模块和类型是 CamelCase。
比较两个版本:
julia> distancematrixfromtricolumn(r)
3×3 Named Matrix{Float64}
A ╲ B │ 1.0 2.0 3.0
──────┼─────────────────
1.0 │ 0.0 0.5 0.75
2.0 │ 0.75 0.0 0.25
3.0 │ 0.5 0.25 0.0
julia> DistanceMatrixFromTriColumn(r) == distancematrixfromtricolumn(r)
true
julia> using BenchmarkTools
julia> @benchmark DistanceMatrixFromTriColumn($r)
BenchmarkTools.Trial: 10000 samples with 8 evaluations.
Range (min … max): 3.897 μs … 535.305 μs ┊ GC (min … max): 0.00% … 98.80%
Time (median): 4.863 μs ┊ GC (median): 0.00%
Time (mean ± σ): 5.828 μs ± 16.267 μs ┊ GC (mean ± σ): 9.92% ± 3.54%
▂▆▇█▇▇▅▃▁
▃▅█████████▇▇▇▆▅▅▆▅▅▄▃▃▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁ ▃
3.9 μs Histogram: frequency by time 10.6 μs <
Memory estimate: 7.39 KiB, allocs estimate: 73.
julia> @benchmark distancematrixfromtricolumn($r)
BenchmarkTools.Trial: 10000 samples with 10 evaluations.
Range (min … max): 1.352 μs … 528.474 μs ┊ GC (min … max): 0.00% … 99.32%
Time (median): 1.543 μs ┊ GC (median): 0.00%
Time (mean ± σ): 1.821 μs ± 8.510 μs ┊ GC (mean ± σ): 8.04% ± 1.72%
▇█▄▁▁▁
███████▆▆▆▅▄▃▃▃▃▂▂▂▂▃▃▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▁▁▁▁▁▁▁▁▁ ▂
1.35 μs Histogram: frequency by time 3.33 μs <
Memory estimate: 2.08 KiB, allocs estimate: 25.
虽然原则上可以考虑其他一些事情来使for
循环更快,但此时我们的大部分执行时间和所有分配都来自unique
对NamedArray
.
推荐阅读
- google-chrome-devtools - Chrome 开发工具“与页面断开连接”
- python - 将变量指定为列表而不在函数中覆盖它
- java - 用于 Netbeans 的 JasperReport 库
- python - 了解 ImageDataGenerator 中的参数和 Keras 中的流程
- neo4j - 次要匹配失败后 Neo4j 主要结果丢失
- pandas - 确定 pandas 数据框的列是否唯一标识行
- javascript - 使用 ++ 和 +1 作为参数的区别
- python - Python - __next__() 方法中的索引如何工作?
- java - 启动画面 Android - 倒计时显示
- python - pandas - 迭代数据帧行,修改它们,并在 for 循环中重建数据帧 pandas