使用 cat 命令实现进度条

3
我正在尝试制作一个简单的控制台进度条,以便查看我的代码进行到哪个阶段。我知道有内置选项,如txtProgressBar和winProgressBar,但我希望能够自己格式化一个。我想让它在同一行更新,而不是输出一系列行。
我目前有一些代码,我觉得应该可以工作 - 有时候也可以正常工作 - 但有时会出现我不理解的故障。这是我的代码:
for(i in 1:10000){
  #Rest of my code
  cat('\r',paste("Working  [",strrep("#",i/n*50),strrep(" ",50-i/n*50),"]   ",ceiling(i/n*100),"%",sep=""))
}

据我所知,这应该每次都能正确格式化。然而,当程序结束时,输出通常看起来像这样:
Working  [##################################################]   100%rking  [                                                 ]   5%

我无法弄清楚出了什么问题。flush.console()和Sys.sleep似乎都没有帮助。如果有任何建议或想法,将不胜感激。如果有影响的话,我正在使用RStudio。

2个回答

2
以下方法在Windows下的R控制台和RStudio中对我都有效:
```html

以下方法在Windows下的R控制台和RStudio中对我都有效:

```
n = 1000
cat("Working: ")
for(i in 1:n) {
    signal = floor(n/200)
    if(!(i %% signal)) { 
        prog = floor(i/n*50)
        cat('\r', "Working  [", strrep("#",prog), 
            strrep(" ", 50-prog), "] ", 2*prog, "%", sep="")
        flush.console() 
      }
    ## Pretend that some work is being done. 
    Sys.sleep(0.001)
    if(i == n) { cat(" \n\r") }
}

谢谢!所以这个想法是更不频繁地更新进度 - 很聪明。由于只有50个字符,我认为您可以使用n/50而不是n/200,而我将使用n/100,以便我可以拥有一个百分比追踪器。当我设置n = 200时,我仍然遇到了您的实现中的原始输出问题(因为每个周期都会触发此条件),我不确定是什么原因,但我将信号设为最小值10,这似乎能正常工作。最后一个问题:在任何参数下使用flush.console(),我都没有注意到任何区别。您能解释一下其中的原因吗? - snowfire257
1
我发现在RStudio中,即使没有使用flush.console,程序也能正常运行。但是在RGui中,如果不加上这个命令,你将看不到任何输出,直到程序结束时所有的输出一次性呈现出来,这样并不实用。 - G5W

2

已经有了轮子,不需要重新发明:


library(dplyr)

n <- 10000
pb <- progress_estimated(n)
for(i in 1:n){
  pb$tick()$print()
  # your code goes here
}

OP提到了另外两个方案,但是他特别关注的是重新创造。 - G5W
是的,但对于这样的事情,建议集中精力完成真正的工作,而不是编写已经被多次解决的代码。这可能会防止其他新手尝试浪费时间。我不在乎答案按钮上的勾号。 - hrbrmstr
我很欣赏你的功能性观点,认为它通常非常有帮助。话虽如此,我想要自己的实现有几个原因。我经常需要使用全新的R安装程序,需要安装的库越少越好(你建议的那个需要安装7个)。还有一些自定义信息我想要放在进度条中,这是我无法使用内置包实现的。最重要的是,我对底层出了什么问题很感兴趣,但不幸的是我仍然不知道出了什么问题。 - snowfire257
这个答案正是我一直在寻找的。这个包已经很轻量,且我已经在使用它来为单行输出提供进度状态和时间估计。我正在从一个URL列表中下载一堆文件,并希望显示进度。这正好符合我的需求,而且不需要我进行任何额外的自定义。再次感谢 dplyr 能够解决我的问题。谢谢你的发布。 - bmosov01

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接