用于循环的矩阵计算

时间:2014-12-20 11:56:55

标签: r matrix

我是R的新手,由于许可证验证问题而从GAUSS迁移过来。

我想加快以下创建n×k矩阵A的代码。给定n×1向量x和参数向量musig(两者都是k维),A创建为A[i,j]=dnorm(x[i], mu[j], sigma[j])。以下代码适用于小数n=40, k=4,但当n大约10^6k大小与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])
}

1 个答案:

答案 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

}

很明显,您要按列填充矩阵AR按列存储矩阵的条目(就像Fortran一样)。 这意味着可以使用dnormxmu的适当重复,通过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

我假设nk的整数倍。

加成

如评论中所述,对于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%。