我正在使用以下脚本分析大量数据:
M <- c_alignment
c_check <- function(x){
if (x == c_1) {
1
}else{
0
}
}
both_c_check <- function(x){
if (x[res_1] == c_1 && x[res_2] == c_1) {
1
}else{
0
}
}
variance_function <- function(x,y){
sqrt(x*(1-x))*sqrt(y*(1-y))
}
frames_total <- nrow(M)
cols <- ncol(M)
c_vector <- apply(M, 2, max)
freq_vector <- matrix(nrow = sum(c_vector))
co_freq_matrix <- matrix(nrow = sum(c_vector), ncol = sum(c_vector))
insertion <- 0
res_1_insertion <- 0
for (res_1 in 1:cols){
for (c_1 in 1:conf_vector[res_1]){
res_1_insertion <- res_1_insertion + 1
insertion <- insertion + 1
res_1_subset <- sapply(M[,res_1], c_check)
freq_vector[insertion] <- sum(res_1_subset)/frames_total
res_2_insertion <- 0
for (res_2 in 1:cols){
if (is.na(co_freq_matrix[res_1_insertion, res_2_insertion + 1])){
for (c_2 in 1:max(c_vector[res_2])){
res_2_insertion <- res_2_insertion + 1
both_res_subset <- apply(M, 1, both_c_check)
co_freq_matrix[res_1_insertion, res_2_insertion] <- sum(both_res_subset)/frames_total
co_freq_matrix[res_2_insertion, res_1_insertion] <- sum(both_res_subset)/frames_total
}
}
}
}
}
covariance_matrix <- (co_freq_matrix - crossprod(t(freq_vector)))
variance_matrix <- matrix(outer(freq_vector, freq_vector, variance_function), ncol = length(freq_vector))
correlation_coefficient_matrix <- covariance_matrix/variance_matrix
模型输入将是这样的:
1 2 1 4 3
1 3 4 2 1
2 3 3 3 1
1 1 2 1 2
2 3 4 4 2
我正在计算的是M[,i]
中找到的每个州的二项式协方差,M[,j]
中找到每个州。每行都是为该试验找到的状态,我想看看列的状态如何共同变化。
澄清:我找到了两个多项分布的协方差,但我是通过二项式比较来做的。
输入是4200 x 510矩阵,每列的c值平均约为15。我知道for
循环在R中非常慢,但我不知道如何在这里使用apply
函数。如果有人建议在这里正确使用apply
,我真的很感激。现在脚本需要几个小时。谢谢!
答案 0 :(得分:15)
我想写评论,但我有太多话要说。
首先,如果您认为申请更快,请查看Is R's apply family more than syntactic sugar?。它可能是,但它远未得到保证。
接下来,请不要在浏览代码时增加矩阵,这会让您的代码变得非常糟糕。预分配矩阵并将其填满,这可以将代码速度提高十倍以上。您通过代码生长不同的向量和矩阵,这是疯狂的(请原谅我强烈的演讲)
然后,查看?subset
的帮助页面及其中的警告:
这是一种便于交互使用的便利功能。对于 编程最好使用标准的子集函数 [,特别是论证子集的非标准评估 可能会产生意想不到的后果。
始终。使用。指数。
此外,您一遍又一遍地重新计算相同的值。例如,fre_res_2
为每个res_2和state_2计算res_1
和state_1
组合的次数。这只是浪费资源。从循环中取出您不需要重新计算的内容,并将其保存在您可以再次访问的矩阵中。
哎呀,现在我来了:请使用矢量化函数。再想一想,看看你能从循环中拖出什么:这就是我所看到的计算核心:
cov <- (freq_both - (freq_res_1)*(freq_res_2)) /
(sqrt(freq_res_1*(1-freq_res_1))*sqrt(freq_res_2*(1-freq_res_2)))
在我看来,你可以构造一个矩阵freq_both,freq_res_1和freq_res_2,并将它们用作那一行的输入。这将是整个协方差矩阵(不要将其称为cov
,cov
是一个函数)。退出循环。输入快速代码。
鉴于我不知道c_alignment中的内容,我不会为你重写你的代码,但你绝对应该摆脱C思维方式并开始思考R. / p>
让这成为一个开始:The R Inferno
答案 1 :(得分:3)
这不是4路嵌套循环,而是代码在每次迭代中增加内存的方式。这已经发生了4次我将# **
放在cbind
和rbind
行上。在这种情况下,R(和Matlab和Python)中的标准建议是提前分配然后填写。这就是apply
函数的作用。只要已知结果数量,它们就会分配list
,将每个结果分配给每个槽,然后在结束时将所有结果合并在一起。在您的情况下,您可以提前分配正确的大小矩阵,并在这4个点(粗略地说)分配。这应该与apply
系列一样快,您可能会发现编码更容易。