我使用函数从多个HWE卡方检验中获取p值。我循环遍历一个名为geno.data
的大矩阵(313行x 355232列)来执行此操作。我基本上逐行循环两列矩阵。它运行得非常慢。我怎样才能让它更快?感谢
library(genetics)
geno.data<-matrix(c("a","c"), nrow=313,ncol=355232)
Num_of_SNPs<-ncol(geno.data) /2
alleles<- vector(length = nrow(geno.data))
HWE_pvalues<-vector(length = Num_of_SNPs)
j<- 1
for (count in 1:Num_of_SNPs){
for (i in 1:nrow(geno.data)){
alleles[i]<- levels(genotype(paste(geno.data[i,c(2*j -1, 2*j)], collapse = "/")))
}
g2 <- genotype(alleles)
HWE_pvalues[count]<-HWE.chisq(g2)[3]
j = j + 2
}
答案 0 :(得分:3)
首先,请注意发布的代码将导致索引越界错误,因为在主循环的Num_of_SNPs
次迭代后,您的j
值将为ncol(geno.data)-1
并且您正在访问列2*j-1
和2*j
。我假设你想要列2*count-1
而2*count
和j
可以删除。
矢量化对于编写快速R代码非常重要。在您的代码中,您每次都会调用paste
函数313次,每次都会传递长度为1的向量。一旦传递长度为313的向量,R在调用paste
时要快得多。以下是主循环的原始和矢量化内部:
# Original
get.pval1 <- function(count) {
for (i in 1:nrow(geno.data)){
alleles[i]<- levels(genotype(paste(geno.data[i,c(2*count -1, 2*count)], collapse = "/")))
}
g2 <- genotype(alleles)
HWE.chisq(g2)[3]
}
# Vectorized
get.pval2 <- function(count) {
g2 <- genotype(paste0(geno.data[,2*count-1], "/", geno.data[,2*count]))
HWE.chisq(g2)[3]
}
我们从矢量化中获得了20倍的加速:
library(microbenchmark)
all.equal(get.pval1(1), get.pval2(1))
# [1] TRUE
microbenchmark(get.pval1(1), get.pval2(1))
# Unit: milliseconds
# expr min lq mean median uq max neval
# get.pval1(1) 299.24079 304.37386 323.28321 307.78947 313.97311 482.32384 100
# get.pval2(1) 14.23288 14.64717 15.80856 15.11013 16.38012 36.04724 100
使用矢量化代码,您的代码应该在大约177616 * .01580856 = 2807.853秒或大约45分钟内完成(相比原始代码为16小时)。如果这对你来说仍然不够快,那么我建议你看一下R中的parallel
包。mcmapply
应该为你提供一个很好的加速,因为外部的每次迭代{{ 1}}循环是独立的。