My question is another "Vector it!". A similar question appeared elsewhere ( Effective way to calculate quadratic forms: avoid loops? ), But for some reason I can't get it to work for my case.
I want to calculate the quadratic shape x'Sxfor each- pdimensional observation xin a sample size n. I could not understand a good, vectorized code, so my last option is to do this for loop. The following example toys p=2, n=100.
set.seed(123)
n <- 100
x1 <- rnorm(n)
x2 <- rnorm(n)
x <- cbind(x1,x2)
Sigma <- matrix(c(1, 2, 3, 4), ncol = 2)
z <- rep(0, n)
for (i in 1:n) {
z[i] <- x[i, ] %*% solve(Sigma, x[i, ]) #quadratic form of x'S^{-1}x
}
Like many other R users who worship vectorized codes, using the for loop caused emotional pain. To alleviate the pain, I modified my code using a couple of common vectorization methods.
ap <- function(Sigma, x) apply(x, 1, function(x) x %*% solve(Sigma, x))
lap <- function(Sigma, x) unlist(lapply(1:n, function(i) x[i, ] %*% solve(Sigma, x[i, ])))
loop <- function(Sigma, x){
z <- rep(0, n)
for (i in 1:n) {
z[i] <- x[i, ] %*% solve(Sigma, x[i, ])
}
z
}
, .
library(microbenchmark)
microbenchmark(lap(Sigma, x), ap(Sigma, x), loop(Sigma, x))
# Unit: milliseconds
# expr min lq mean median uq max neval
# lap(Sigma, x) 4.207434 4.444895 5.092389 4.616912 5.283504 8.440802 100
# ap(Sigma, x) 4.360204 4.523306 5.317304 4.685396 5.412771 10.168674 100
# loop(Sigma, x) 4.518645 4.679317 6.204626 4.827831 5.438908 94.115144 100
, Rcpp, for loops?