高效访问成对距离

6

我有一个距离矩阵:

> mat
          hydrogen   helium  lithium beryllium    boron
hydrogen  0.000000 2.065564 3.940308  2.647510 2.671674
helium    2.065564 0.000000 2.365661  1.697749 1.319400
lithium   3.940308 2.365661 0.000000  3.188148 2.411567
beryllium 2.647510 1.697749 3.188148  0.000000 2.499369
boron     2.671674 1.319400 2.411567  2.499369 0.000000

还有一个数据框:

> results

El1      El2    Score
Helium Hydrogen   92
Boron   Helium    61
Boron  Lithium    88

我希望计算出results$El1results$El2中所有单词之间的两两距离,得到以下结果:
> results

El1      El2    Score   Dist
Helium Hydrogen   92    2.065564
Boron   Helium    61    1.319400
Boron  Lithium    88    2.411567

我用for循环实现了这个功能,但代码看起来很笨重。有没有更优雅的方式来搜索和提取距离,使代码行数更少?

以下是我的当前代码:

names = row.names(mat) 
num.results <- dim(results)[1]   
El1 =  match(results$El1, names)  
El2 = match(results$El2, names)    
el.dist <- matrix(0, num.results, 1)        
for (i1 in c(1:num.results)) {             
el.dist[i1, 1] <- mat[El1[i1], El2[i1]]
}
results$Dist = el.dist[,1] 
2个回答

4
cols <- match(tolower(results$El1), colnames(mat))
rows <- match(tolower(results$El2), colnames(mat))
results$Dist <- mat[cbind(rows, cols)]
results
     El1      El2 Score     Dist
1 Helium Hydrogen    92 2.065564
2  Boron   Helium    61 1.319400
3  Boron  Lithium    88 2.411567

你会认出大部分的代码。需要关注的是mat[cbind(rows, cols)]。在矩阵中,我们可以使用与维度相同列数的另一个矩阵来进行子集操作。从?`[`帮助文档中可以看到:

当用单个参数i索引数组时,i可以是具有与x维数相同的列数的矩阵;结果将是一个向量,其元素对应于i每行中的索引集。


在发现问题后,我删除了先前的评论:一个不该出现的大写字母! - Dex

3
另一种方法
results$Dist <- mapply(function(x, y) mat[tolower(x), tolower(y)],
                       results$El1, results$El2)

这假设resultsEl1El2中使用character而不是factor

结果为:

> results
     El1      El2 Score     Dist
1 Helium Hydrogen    92 2.065564
2  Boron   Helium    61 1.319400
3  Boron  Lithium    88 2.411567

谢谢!我刚试了一下,即使El1El2是因子,它也可以正常工作。不建议使用mapply与因子吗? - Dex
1
@user20672 - 因子/字符的差异将会改变当使用整数字符进行索引时返回的结果。因子在内部是一个整数...所以 x <- c(b=1,a=2) 然后 x[factor(c("a","b"))]x[c("a","b")] 将会返回不同的答案。 - thelatemail

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接