使嵌套循环更有效?

Mic*_*ine 5 r r-faq

我正在使用以下脚本分析大量数据:

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
Run Code Online (Sandbox Code Playgroud)

模型输入将是这样的:

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
Run Code Online (Sandbox Code Playgroud)

我正在计算是每个国家的二项式方差发现M[,i],在发现的每个状态M[,j].每行都是为该试验找到的状态,我想看看列的状态如何共同变化.

澄清:我找到了两个多项分布的协方差,但我是通过二项式比较来做到的.

输入是4200 x 510矩阵,每列的c值平均约为15.我知道forR中的循环速度非常慢,但我不确定如何在apply这里使用该函数.如果有人建议apply在这里正确使用,我真的很感激.现在脚本需要几个小时.谢谢!

Jor*_*eys 15

我想写评论,但我有太多话要说.

首先,如果你认为申请更快,那么看看R的申请家庭比语法糖更多吗?.它可能是,但它远没有保证.

接下来,请不要在浏览代码时增加矩阵,这会令您的代码变得非常糟糕.预分配矩阵并将其填满,这可以将代码速度提高十倍以上.你通过你的代码生长不同的向量和矩阵,这是疯了(请原谅我强烈的演讲)

然后,查看帮助页面?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))) 
Run Code Online (Sandbox Code Playgroud)

在我看来,你可以构造一个矩阵freq_both,freq_res_1和freq_res_2,并将它们用作那一行的输入.这将是整个协方差矩阵(不称之为cov,cov是一个功能).退出循环.输入快速代码.

鉴于我不知道c_alignment中有什么,我不会为你重写你的代码,但你绝对应该摆脱C思维方式并开始思考R.

让这成为一个开始:R Inferno


Mat*_*wle 3

这并不是真正的 4 路嵌套循环,而是代码在每次迭代中增加内存的方式。在我放置 和 行的地方,这种情况发生了# **4cbindrbind。在这种情况下,R(以及 Matlab 和 Python)中的标准建议是提前分配,然后填充。这就是函数的作用apply。他们分配list已知数量的结果,将每个结果分配给每个槽,然后在最后将所有结果合并在一起。在你的情况下,你可以提前分配正确的大小矩阵,并在这 4 个点上分配给它(粗略地说)。这应该和apply家庭一样快,而且您可能会发现编码更容易。