在R中计算向量内所有成对差异

21

在计算机领域中,有很多关于计算向量之间成对差异的帖子,但我找不到如何计算向量内部所有差异的方法。

假设我有一个向量v。

v<-c(1:4)

我希望生成一个第二个向量,该向量包含在原向量中所有成对差的绝对值。类似于:

abs(1-2) = 1
abs(1-3) = 2
abs(1-4) = 3
abs(2-3) = 1
abs(2-4) = 2
abs(3-4) = 1
输出将是一个由6个值组成的向量,这6个值是我进行6次比较的结果。
output<- c(1,2,3,1,2,1)

R中是否有能够实现此功能的函数?

3个回答

22
as.numeric(dist(v))

看起来能够工作;它将v视为列矩阵并计算行之间的欧几里得距离,在这种情况下是sqrt((x-y)^2)=abs(x-y)

如果我们进行高尔夫比赛,那我会提供等效的c(dist(v)),我猜这将是无法被超越的。

@AndreyShabalin提出了一个好观点,使用method="manhattan"可能会稍微更有效,因为它避免了平方/平方根的操作。


3
为了避免使用平方根,你可以使用另一种度量方法:as.vector(dist(v, method = "manhattan")) - Andrey Shabalin
嗯,出了点问题。不知何故,解决方案偏差了100倍。 - Vlo

15

让我们打高尔夫球

abs(apply(combn(1:4,2), 2, diff))

@Ben,你的简直太棒了!

> system.time(apply(combn(1:1000,2), 2, diff))
   user  system elapsed 
   6.65    0.00    6.67 
> system.time(c(dist(1:1000)))
   user  system elapsed 
   0.02    0.00    0.01 
> system.time({
+ v <- 1:1000
+ z = outer(v,v,'-');
+ z[lower.tri(z)];
+ })
   user  system elapsed 
   0.03    0.00    0.03 

谁知道优雅(可以理解/灵活)的代码会这么慢。


3
你能击败 c(dist(v)) 吗?(10个字符)如果你用 1:4 替代 v,你的答案可能会稍微更短一些。 - Ben Bolker
哎呀!我本以为 @BenBolker 会赢得比赛。我认为我的示例在一行中引入了三个常用函数作为额外奖励。 - mlt
看看基准测试的结果会很有趣,如果@Vlo真的这样做的话。这个解决方案执行的操作不到一半,但效率较低。 - Ben Bolker
1
我们都可以转向Julia :-) - Ben Bolker
5
combn函数有一个FUN参数,所以你可以这样做:combn(v,2,FUN=diff)。这将对向量v中的所有元素进行组合,并且将其中每一对元素应用diff函数。 - Matthew Plourde
显示剩余2条评论

14
一个可能的解决方案是:
z = outer(v,v,'-'); 
z[lower.tri(z)];

[1] 1 2 3 1 2 1

3
分号并非必要的,稍微有点效率低下(会计算完整的矩阵),但除此之外非常好。 - Ben Bolker
在查看这里之前,我使用了 sapply(v, "-", v)outer很好用! - PatrickT

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