R代码耗时太长

时间:2011-09-06 16:32:01

标签: r for-loop execute

我运行了以下代码,这需要我很长时间才能运行。我怎么知道它是否还在做它的工作还是卡在某个地方。

noise4<-NULL;
for(i in 1:length(noise3))
{
    if(is.na(noise3[i])==TRUE)
    {
    next;
    }
    else
    {
    noise4<-c(noise4,noise3[i]);
    }
}

noise3是具有2418233个数据点的向量。

4 个答案:

答案 0 :(得分:10)

您只想删除NA值。这样做:

noise4 <- noise3[!is.na(noise3)]

这几乎是即时的。

或者约书亚建议,一个更具可读性的选择:

noise4 <- na.omit(noise3)

你的代码很慢,因为:

  1. 它使用显式循环,在R解释器下往往很慢。
  2. 每次迭代都会重新分配内存。
  3. 内存重新分配可能是您代码的最大障碍。

答案 1 :(得分:5)

我想说明预分配的好处,所以我试着运行你的代码......但是我在约5分钟后杀了它。我建议您使用noise4 <- na.omit(noise3),正如我在评论中所说的那样。此代码仅用于说明目的。

# Create some random data
set.seed(21)
noise3 <- rnorm(2418233)
noise3[sample(2418233, 100)] <- NA

noise <- function(noise3) {
  # Pre-allocate
  noise4 <- vector("numeric", sum(!is.na(noise3)))
  for(i in seq_along(noise3)) {
    if(is.na(noise3[i])) {
      next
    } else {
      noise4[i] <- noise3[i]
    }
  }
}

system.time(noise(noise3)) # MUCH less than 5+ minutes
#    user  system elapsed 
#    9.50    0.44    9.94 

# Let's see what we gain from compiling
library(compiler)
cnoise <- cmpfun(noise)
system.time(cnoise(noise3))  # a decent reduction
#    user  system elapsed 
#    3.46    0.49    3.96 

答案 2 :(得分:4)

其他答案为您提供了更多,更好的方法来完成您实际要实现的任务(删除数据中的NA值),但回答了您提出的具体问题(“如何我是否知道R是否实际正在工作或是否已经卡住?“)是在循环中引入一些输出(cat)语句,如下所示:

rpt <- 10000  ## reporting interval
noise4<-NULL;
for(i in 1:length(noise3))
{
    if (i %% rpt == 0) cat(i,"\n")
    if(is.na(noise3[i])==TRUE)
    {
    next;
    }
    else
    {
    noise4<-c(noise4,noise3[i]);
    }
}

如果您运行此代码,您可以立即看到它在循环中越来越慢(未能预先分配空间的结果)...

答案 3 :(得分:2)

其他人都有正确的方法来解决同样的问题,所以你不必担心速度。 @BenBolker也提供了关于常规输出的好指针。

另一件需要注意的事情是,如果你发现自己处于循环中,你可以突破它并找到i的值。假设从i的值重新开始不会损害事物,即使用该值两次不会有问题,您可以重新启动。或者,您可以像其他人所说的那样完成工作。

另一个技巧是,如果循环缓慢(并且无法进行矢量化,或者您不想急于退出循环), AND 您没有任何报告,您仍然可以查找外部方法,以查看R是否实际消耗了计算机上的周期。在Linux中,top命令是您最好的选择。在Windows上,任务管理器将执行操作(我更喜欢使用SysInternals / Microsoft程序Process Explorer)。 “顶级”也存在于Mac上,但我相信还有一些其他更受欢迎的工具。

另一个建议是:如果你有一个很长的循环运行,我强烈建议定期保存结果。我通常创建一个名称为myPrefix_YYYYMMDDHHMMSS.rdat的文件。这样一切都可以下地狱,你仍然可以从你离开的地方开始循环。

我并不总是迭代,但是当我这样做时,我会使用这些技巧。保持快速,我的朋友。