假设我有一个像这样的值向量:
M=3;val<-rnorm(M)
和相应的索引矩阵,例如:
N=20;J=10;ind<-matrix(sample(1:M,N*J,replace=T),nrow=J)
我可以轻松地将值及其索引分配给数据矩阵,如下所示:
x<-matrix(val[ind],J,N)
现在,我有一个值矩阵,如:
val<-matrix(rnorm(M*J),nrow=J)
并且需要逐行分配值和索引(即val中的一行与ind中的一行)以获取数据矩阵。
我可以使用for循环来做到这一点:
x<-ind;
for(j in 1:J){x[j,]<-val[j,ind[j,]]}
但是我想知道是否有更有效的方法来做到这一点,尤其是避免使用for循环?
我需要重新采样并重复分配过程数十万次。因此,我担心for循环会占用大量时间。
另三种方法,一种使用sapply
,一种矩阵子集和一种向量子集。矩阵和向量子集看起来sapply
比for循环要快,但子集要慢。
目前
matrix(val[1:J + (ind-1)*J],J,N)
看起来是最快的方法。
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
速度比较:
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
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句