我在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()
}
目前,代码正在运行,但是进度条似乎立即完成,而实际过程仍在运行。我以为我没有将进度条放在循环中的正确位置?
答案 0 :(得分:2)
通过键入?txtProgressBar
,您将被定向到该功能的帮助文件。在这里,您将看到另外两个功能getTxtProgressBar
和setTxtProgressBar
。顾名思义,这些可用于获取和设置任何实例化进度条上的当前进度。
以您的示例为例,请尝试在您的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'