【问题标题】:Improving R script efficiency提高 R 脚本效率
【发布时间】:2013-01-09 16:34:52
【问题描述】:

我正在尝试编写一个 R 脚本,作为第一步,为输入矩阵的每一行计算 dist() 和其他内容,然后作为脚本的第二步,使用在进行另一次计算的第一步。 我的问题是我无法“保存”从第一步获得的所有矩阵。谁能告诉我一个好的策略?

我的代码如下所示:

n<- nrow (aa)
output <- matrix (0, n, n)
for (i in 1:n)
{
    for (j in i:n)
    {
        akl<- function (dii){
            ddi<- as.matrix (dii)
            m<- rowMeans(ddi)
            M<- mean(ddi)
            r<- sweep (ddi, 1, m)
            b<- sweep (r, 2, m)
            return (b + M)  
            }
        A<- akl(dist(aa[i,]))
        B<- akl(dist(aa[j,]))
            V <- sqrt ((sqrt (mean(A * A))) * (sqrt(mean(B * B))))
        if (V > 0) {
            output[i,j] <- (sqrt(mean(A * B))) / V else output[i,j] <- 0
            }
    }
}   

我想从akl 函数中获取所有生成的矩阵,然后将它们用于其余的计算。 我在这里展示的脚本在时间方面非常昂贵,因为它每次都计算 akl,而且对于大型输入矩阵是一个问题。

【问题讨论】:

  • 在尝试避免嵌套的 for 循环并可能进行矢量化之前,将 else 替换为 } else {

标签: r


【解决方案1】:

你不需要在 j 循环内重新计算 A,把它带到外面。

另外,您不需要每次都重新定义循环内的函数(假设它不依赖于循环内的任何内容)。

n<- nrow (aa)
output <- matrix (0, n, n)
akl<- function (dii){
            ddi<- as.matrix (dii)
            m<- rowMeans(ddi)
            M<- mean(ddi)
            r<- sweep (ddi, 1, m)
            b<- sweep (r, 2, m)
            return (b + M)  
            }
for (i in 1:n)
{
    A<- akl(dist(aa[i,]))
    for (j in i:n)
    {
        B<- akl(dist(aa[j,]))
            V <- sqrt ((sqrt (mean(A * A))) * (sqrt(mean(B * B))))
        if (V > 0) {
            output[i,j] <- (sqrt(mean(A * B))) / V else output[i,j] <- 0
            }
    }
}   

试试看,运行你的测试(你写过测试,对吧?)然后看看。

【讨论】:

  • 我在一个相当大的测试矩阵 (400x400) 上进行了尝试。尊重我的脚本更快(需要我的脚本所需时间的一半)。问题是我必须在 5000x700 矩阵上使用它......无论如何这将花费很多时间!其他改进/建议?谢谢
  • 为了真正的速度,用 C 或 C++ 重写整个东西,并使用 RCpp。在任何编程语言中加快速度的一般准则都适用 - 编写测试用例,分析您的代码(参见 ?Rprofile),然后优化花费最多时间的位。
  • 你可以做更多微小的改变(例如,sqrt(mean(A*A)) 在 j 循环中是恒定的,所以把它放在外面)但是如果你想要数量级的加速你需要重新考虑。
  • 从哪个角度重新思考?用C重写并使用RCpp或其他意义?
  • 从各个方面重新思考:从数据中抽取子样本,考虑并行运行或在集群上运行,寻找新算法,辞掉工作,在某个海滩上以艺术家的身份生活......
【解决方案2】:

现在您已经对编译器包进行了代码改进。通过使用带有 enablejit(3) 的编译器,您可以节省大量循环脚本的时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-20
    相关资源
    最近更新 更多