rmatrix-multiplicationcross-product

# Vectorising a cross product of vector and matrix with consecutive indices in R

Some context: I have a vector e of dimensions n×1, and a correlation matrix R of n×n. I am trying to efficiently calculate the quantity

in R, without looping. So far, I have been able to do it with a single loop, using the following code:

``````nom <- 0; denom <- 0
for(i in 1:n){
nom <- nom + e[i]*(R[i,-(1:i)]%*%e[-(1:i)])
denom <- denom + e[i]*sum(e[-(1:i)])
}
beta <- nom/denom
``````

This works, and in practice my calculations should not take long because for the task at hand, n will be at most of size 11 or 12 (so an improvement will likely not make a huge difference in measured time performance). However, I am curious as to how this can be done more efficiently, since

a) R is symmetrical and the calculations only need to use the part above (or below) the main diagonal of R, and

b) I am planning to use this in some MC simulations of a large size, so any calculation time I can shave off might make a difference for the big picture.

For replication/calculation purposes, here is an example of possible numerical values:

``````e <- c(0.4972,0.0902,0.02822,0.1688,0.0149,0.0028,0.01411,0.02733,0.0151,0.0391,0.01301,0.0894)
R <- matrix(data = c(1,0.9,0.4,0.75,0.5,0.3,0.4,0.4,0.25,0.25,0.5,0.4,0.9,1,0.5,0.9,0.5,0.3,0.4,0.35,0.2,0.2,0.5,0.3,0.4,0.5,1,0.3,0.5,0.4,0.25,0.2,0.2,0.2,0.3,0.3,0.75,0.9,0.3,1,0.3,0.3,0.4,0.25,0.25,0.2,0.3,0.75,0.5,0.5,0.5,0.3,1,0.5,0.35,0.8,0.8,0.3,0.7,0.45,0.3,0.3,0.4,0.3,0.5,1,0.3,0.4,0.3,0.2,0.45,0.35,0.4,0.4,0.25,0.4,0.35,0.3,1,0.3,0.3,0.2,0.5,0.5,0.4,0.35,0.2,0.25,0.8,0.4,0.3,1,0.8,0.2,0.6,0.8,0.25,0.2,0.2,0.25,0.8,0.3,0.3,0.8,1,0.3,0.7,0.8,0.25,0.2,0.2,0.2,0.3,0.2,0.2,0.2,0.3,1,0.25,0.3,0.5,0.5,0.3,0.3,0.7,0.45,0.5,0.6,0.7,0.25,1,0.7,0.4,0.3,0.3,0.75,0.45,0.35,0.5,0.8,0.8,0.3,0.7,1), nrow = 12, ncol = 12)
``````

Solution

• You can do:

``````ee <- tcrossprod(e)
ee0 <- ee; diag(ee0) <- 0

sum(R*ee0)/sum(ee0)
``````

``````> sum(R*ee0)/sum(ee0)
[1] 0.5647038
``````

A little save of calculation: `sum(ee0)` is equal to

``````sum(e)^2 - sum(e^2)
``````

Here is another variant:

``````d <- diag(R)
diag(R) <- 0
sum(e*crossprod(e, R))/(sum(e)^2 - sum(e^2))
``````