我在哪里将进度条代码插入嵌套循环中?

时间:2019-02-10 15:26:27

标签: r

我在R中有一个嵌套的“ for”循环,该循环在大型数据帧上运行(超过6000个变量超过80,000 obvs),并根据其他变量中的值将值分配给新列。

由于数据帧的大小,以及我正在测试对循环的多次编辑的事实,我想插入一个进度条,以便更了解可能需要花费多长时间。

到目前为止,我已经尝试过:

# create an example dataset
id <- c(1,2,3,4,5,6,7,8,9,10)
capital1 <- replicate(1,sample(0:100,10,rep=TRUE))
capital2 <- replicate(1,sample(0:100,10,rep=TRUE))
capital3 <- replicate(1,sample(0:100,10,rep=TRUE))
capital4 <- replicate(1,sample(0:100,10,rep=TRUE))
capital5 <- replicate(1,sample(0:100,10,rep=TRUE))
capital6 <- replicate(1,sample(0:100,10,rep=TRUE))
capital7 <- replicate(1,sample(0:100,10,rep=TRUE))
capital8 <- replicate(1,sample(0:100,10,rep=TRUE))
capital9 <- replicate(1,sample(0:100,10,rep=TRUE))
capital10 <- replicate(1,sample(0:100,10,rep=TRUE))

data <- data.frame(id, capital1, capital2, capital3, capital4,
capital5, capital6, capital7, capital8, capital9, capital10)

# create new column to populate with results of loop
nrows<-length(data[,1])
AFT<-rep("N_A",nrows)

# set up progress bar for loop
total <- nrows
pb <- txtProgressBar(min = 0, max = length(total), style = 3)

# for loop
for (i in c(1:nrows)) { 

    Sys.sleep(.1)

    # Mask out waterbodies and dense artifical (urban) areas
    if (data$capital1[i]>70) {
        AFT[i]<-'water.urban'} 

    if (data$capital2[i]>70) {
        AFT[i]<-'water.urban'} 

    if (data$capital3[i]+data$capital4[i]>=60){
        AFT[i]<-'multi.mixed'}
    if (data$capital4[i]>70) {
        AFT[i]<-'multi.nb'}

    # etc. (10+ more loops assigning different AFTs)

    # print progress as loop runs
    cat("\r", i, "of", 10, "\r") 
    flush.console()

}

目前,代码正在运行,但是进度条似乎立即完成,而实际过程仍在运行。我以为我没有将进度条放在循环中的正确位置?

2 个答案:

答案 0 :(得分:2)

通过键入?txtProgressBar,您将被定向到该功能的帮助文件。在这里,您将看到另外两个功能getTxtProgressBarsetTxtProgressBar。顾名思义,这些可用于获取和设置任何实例化进度条上的当前进度。

以您的示例为例,请尝试在您的for循环中希望更新进度的位置添加setTxtProgressBar(pb, i)。所选地点可以在任何地方,具体取决于您希望显示进度的时间和频率。例如,作为您的特定示例,进度条具有一个最大值,该最大值在迭代i时也会使用,因此可以在如下所示的for循环开始时更新进度条。

for (i in c(1:nrows)) { 
  setTxtProgressBar(pb, i)
  ...
}
close(pb)

请注意循环后我如何使用close(pb)关闭进度条。

答案 1 :(得分:2)

不要使用for循环来遍历80,000行,而要使用R的矢量化功能。您可以使用which函数选择要更新的AFT值。 which函数返回索引的向量,其中比较为TRUE。这将使您的for循环性能提高1000倍,从而使进度条过时。

例如,您的作业将类似于:

AFT[which(data$capital1>70)] <-'water.urban'
AFT[which(data$capital2>70)] <-'water.urban'
AFT[which((data$capital3+data$capital4)>=60)]<-'multi.mixed'
AFT[which(ata$capital4>70)]<-'multi.nb'