我是R
的新手,由于许可证验证问题而从GAUSS
迁移过来。
我想加快以下创建n×k
矩阵A
的代码。给定n×1
向量x
和参数向量mu
,sig
(两者都是k维),A
创建为A[i,j]=dnorm(x[i], mu[j], sigma[j])
。以下代码适用于小数n=40, k=4
,但当n
大约10^6
且k
大小与n^{1/3}
大小相同时,代码会显着减慢。
我正在进行模拟实验以验证引导程序的有效性,因此我需要重复计算A
次#ofsimulation × #bootstrap
次矩阵,因为我想要尝试许多不同的值n,k
。我尽可能多地对代码进行了矢量化(感谢dnorm
的矢量参数),但是我可以要求更快的速度吗?
先发制人,谢谢您的帮助。
x = rnorm(40)
mu = c(-1,0,4,5)
sig = c(2^2,0.5^2,2^2,3^2)
n = length(x)
k = length(mu)
A = matrix(NA,n,k)
for(j in 1:k){
A[,j]=dnorm(x,mu[j],sig[j])
}
答案 0 :(得分:2)
您的方法可以放入这样的函数
A.fill <- function(x,mu,sig) {
k <- length(mu)
n <- length(x)
A <- matrix(NA,n,k)
for(j in 1:k) A[,j] <- dnorm(x,mu[j],sig[j])
A
}
很明显,您要按列填充矩阵A
。
R
按列存储矩阵的条目(就像Fortran一样)。
这意味着可以使用dnorm
,x
和mu
的适当重复,通过sig
的单个调用来填充矩阵。向量z
将堆叠所需矩阵的列。然后,只需通过指定列的行数,就可以从该向量形成要返回的矩阵。请参阅以下功能
B.fill <- function(x,mu,sig) {
k <- length(mu)
n <- length(x)
z <- dnorm(rep(x,times=k),rep(mu,each=n),rep(sig,each=n))
B <- matrix(z,nrow=n,ncol=k)
B
}
让我们以您的数据为例进行测试,并按如下方式进行测试:
N <- 40
set.seed(11)
x <- rnorm(N)
mu <- c(-1,0,4,5)
sig <- c(2^2,0.5^2,2^2,3^2)
A <- A.fill(x,mu,sig)
B <- B.fill(x,mu,sig)
all.equal(A,B)
# [1] TRUE
我假设n
是k
的整数倍。
如评论中所述,对于n
的大值,B.fill非常慢。
原因在于构造rep(...,each=...)
。
有没有办法加快A.fill
的速度。
我测试了这个功能:
C.fill <- function(x,mu,sig) {
k <- length(mu)
n <- length(x)
sapply(1:k,function(j) dnorm(x,mu[j],sig[j]), simplify=TRUE)
}
此功能比A.fill快约20%。