colin
colin

Reputation: 2666

compute all pairwise differences within a vector in R

There are several posts on computing pairwise differences among vectors, but I cannot find how to compute all differences within a vector.

Say I have a vector, v.

v<-c(1:4)

I would like to generate a second vector that is the absolute value of all pairwise differences within the vector. Similar to:

abs(1-2) = 1
abs(1-3) = 2
abs(1-4) = 3
abs(2-3) = 1
abs(2-4) = 2
abs(3-4) = 1

The output would be a vector of 6 values, which are the result of my 6 comparisons:

output<- c(1,2,3,1,2,1)

Is there a function in R that can do this?

Upvotes: 24

Views: 20941

Answers (3)

mlt
mlt

Reputation: 1659

Let's play golf

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

@Ben, yours is a killer!

> 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 

Who knew that elegant (read understandable/flexible) code can be so slow.

Upvotes: 16

Ben Bolker
Ben Bolker

Reputation: 226522

as.numeric(dist(v))

seems to work; it treats v as a column matrix and computes the Euclidean distance between rows, which in this case is sqrt((x-y)^2)=abs(x-y)

If we're golfing, then I'll offer c(dist(v)), which is equivalent and which I'm guessing will be unbeatable.

@AndreyShabalin makes the good point that using method="manhattan" will probably be slightly more efficient since it avoids the squaring/square-rooting stuff.

Upvotes: 25

Andrey Shabalin
Andrey Shabalin

Reputation: 4614

A possible solution is:

z = outer(v,v,'-'); 
z[lower.tri(z)];

[1] 1 2 3 1 2 1

Upvotes: 16

Related Questions