Vector to matrix of differences between elements

For the vector:

vec <-1:5

What is an effective way to create a matrix, where the difference between the vector components is displayed in the matrix, the difference matrix, if you want. I could do this with two loops, but I need to do this with a much larger dataset. There is probably a term for this matrix that I am trying to make, but I was not lucky to find it. Here is how the result will look.

m<-matrix(c(NA), ncol=5, nrow=5, byrow=TRUE)
rownames(m)<-1:5;colnames(m)<-1:5
for(i in 1:5){for(j in 1:5){m[i,j]<-(as.numeric(rownames(m)[i])-as.numeric(rownames(m)[j]))}}
m

Thanks for any help!

+4
source share
3 answers

This is usually done using outer.

outer(1:5, 1:5, '-')

See more details ?outer.

+11
source

Possible Solution:

matrix(vec, 5, 5, byrow=TRUE) - matrix(vec, 5, 5, byrow=FALSE)

or even

matrix(vec, 5, 5, byrow=TRUE) - vec

hardcoded 5, .

+2

I would use a function vapply- it is not much slower than the approach matrix... and I do not like how the outerresult returns. See below:

dd <- 1:5
vapply(seq_along(dd), 
       FUN = function(i, X) X[[i]] - X, 
       FUN.VALUE = numeric(length(dd)), 
       dd)

vf <- function() vapply(seq_along(dd), 
                        FUN = function(i, X) X[[i]] - X, 
                        FUN.VALUE = numeric(length(dd)), 
                        dd)

mf <- function() matrix(dd, length(dd), length(dd), byrow=T) - 
                 matrix(dd, length(dd), length(dd), byrow=FALSE)

microbenchmark(vf(), mf(), times = 1e4)

Unit: microseconds
 expr    min     lq      mean median     uq     max neval cld
 vf() 20.527 22.037 26.678118 22.942 24.149 785.434  1000   b
 mf()  4.227  4.831  6.343785  5.132  5.434 503.499  1000  a 
+1
source

All Articles