Another three methods, one using sapply, one matrix subsetting and one vector subsetting. Matrix and vector subsetting looks to be faster, the one with sapply slower, than the for loop.
Currently
matrix(val[1:J + (ind-1)*J],J,N)
looks like to be the fastest way.
M <- 3; N <- 20; J <- 10
ind <- matrix(sample(1:M,N*J,replace=T),nrow=J)
val <- matrix(rnorm(M*J),nrow=J)
x<-ind;
for(j in 1:J){x[j,]<-val[j,ind[j,]]}
identical(x, t(sapply(1:J, function(j) val[j,ind[j,]])))
#[1] TRUE
identical(x, matrix(val[matrix(c(rep(1:J, N), ind), ncol=2)],J,N))
#[1] TRUE
#Other ways for rep(1:J, N)
identical(x, matrix(val[matrix(c(row(ind), ind), ncol=2)],J,N))
#[1] TRUE
identical(x, matrix(val[matrix(c(slice.index(ind, 1), ind), ncol=2)],J,N))
#[1] TRUE
#Vector subsetting as suggested by Aaron
identical(x, matrix(val[row(ind) + (ind-1)*J],J,N))
#[1] TRUE
#Other ways
identical(x, matrix(val[1:J + (ind-1)*J],J,N))
#[1] TRUE
identical(x, matrix(val[sweep((ind-1)*J, 1, 1:J, "+")],J,N))
#[1] TRUE
Speed comparison:
library(microbenchmark)
f1 <- function() {
x<-ind;
for(j in 1:J){x[j,]<-val[j,ind[j,]]}
}
f2 <- function() {t(sapply(1:J, function(j) val[j,ind[j,]]))}
f3 <- function() {matrix(val[matrix(c(row(ind), ind), ncol=2)],J,N)}
f4 <- function() {matrix(val[row(ind) + (ind-1)*J],J,N)} #Comment from Aaron
f5 <- function() {matrix(val[1:J + (ind-1)*J],J,N)}
microbenchmark(f1(), f2(), f3(), f4(), f5(), setup=gc)
#Unit: microseconds
# expr min lq mean median uq max neval
# f1() 16.540 18.3595 20.11216 19.8820 20.7915 36.201 100
# f2() 43.514 46.3650 49.77573 48.0320 49.5120 113.631 100
# f3() 8.325 9.3265 10.38931 9.9425 10.4825 46.561 100
# f4() 6.934 7.8270 9.00286 8.4405 9.1355 25.840 100
# f5() 5.839 6.8730 7.71322 7.3520 8.3145 16.349 100