Element wise subtraction of a vector?

Viewed 293

I have the following vector in R

x<-c(5,7,8,20,11,30)

I want to get all the possible subtractions xi-xj, 1<=i<j<=6. I used outer function but I got a matrix with zero diagonal. I do not want to have xi-xj with i=j. Additionally, I want to have a vector, not a matrix.

3 Answers

You can subset the output of outer using lower.tri or upper.tri.

y <- outer(x, x, '-')
y[lower.tri(y)]
# [1]  2  3 15  6 25  1 13  4 23 12  3 22 -9 10 19

Alternatively you can generate the indices using seq and rep.

k <- seq(length(x) - 1, 1)
i <- rep(seq_along(k), k)
j <- sequence(k) + i
x[j] - x[i]
# [1]  2  3 15  6 25  1 13  4 23 12  3 22 -9 10 19

Yes, outer generates a matrix with all possible combinations in both the directions (a - b and b - a) which is unnecessary in this case.

Perhaps, you can use combn :

combn(x, 2, diff)
#[1]  2  3 15  6 25  1 13  4 23 12  3 22 -9 10 19

Also as @Rui Barradas points out that outer might not be the right solution since it fails for the condition 1<=i<j<=6.

Higher order functions; less succinct/readable than above but quicker for some reason.

Filter(function(y) {y != 0},
   do.call("c", (Map(function(i){y <- x - x[i]; y[i:length(x)]}, seq_along(x)))))
Related