【问题标题】:Progress bar to visualize for loop ETA用于可视化循环 ETA 的进度条
【发布时间】:2019-12-12 16:17:47
【问题描述】:

我的代码中有这一行

lev_similarity = -1*np.array([[distance.levenshtein(w1,w2) for w1 in words] for w2 in words])

这需要很长时间,所以我想包含一个带有 ETA 的进度条,以显示预计的处理时间。

如何在给定这个内部循环的情况下包含进度条?

我的做法:

npa = []
akt = 1
with progressbar.ProgressBar(max_value=len(words)) as bar:
    for w2 in words:
        bar.update(akt)
        akt = akt + 1
        for w1 in words:
            npa.append(distance.levenshtein(w1,w2))
lev_similarity = -1*np.array(npa)

【问题讨论】:

    标签: python python-3.x for-loop


    【解决方案1】:

    TQDM 库 (https://pypi.org/project/tqdm/) 为 python 中的进度条提供了一个非常简单的界面。

    它会变成 s.t.h.喜欢:

    from tqdm import tqdm
    
    ... code ...
    
    new_arr = -1*np.array([[distance.levenshtein(w1,w2) for w1 in words] for w2 in tqdm(words)])
    

    tqdm 手册中有一个关于嵌套循环的部分。

    【讨论】:

      【解决方案2】:

      您可以在循环内部使用循环而不是列表推导,并在内部或外部循环中更新进度条。 如果您仍然想要列表推导,您可以定义一个既执行计算又更新进度条的函数,如下所示:

      def calc(w1, w2):
          update_progress_bar()
          return distance.levenshtein(w1,w2)
      

      然后列表推导将变为:

       -1*np.array([[calc(w1,w2) for w1 in words] for w2 in tqdm(words)])
      

      IMO 列表推导应该只创建值而不产生任何副作用,因此虽然简短且可以说是优雅的,但我会在循环中使用循环。在这种情况下,它对软件工程更友好。

      【讨论】:

        【解决方案3】:

        我使用自己的小功能来做到这一点。我认为它也可能适用于您的情况。

        def print_pbar(n,m,s='|#.|',size=30,message=''):
            '''(int,int,string,int) => None
            Print a progress bar using the simbols in 's'.
            Example:
                range_limit = 1000
                for n in range(range_limit):
                    print_pbar(n+1,m=range_limit)
                    time.sleep(0.1)
            '''
            #adjust to bar size
            if m != size:
                n =(n*size)/m
                m = size
            #calculate ticks
            _a = int(n)*s[1]+(int(m)-int(n))*s[2]
            _b = round(n/(int(m))*100,1)
            #adjust overflow
            if _b >= 100:
                _b = 100.0
            #to stdout    
            sys.stdout.write(f'\r{message}{s[0]}{_a}{s[3]} {_b}%     ')
            sys.stdout.flush()
        
        
        npa = []
        for n, w2 in enumerate(words):
            print_pbar(n+1, len(words))
            for w1 in words:
                npa.append(distance.levenshtein(w1,w2))
        

        【讨论】:

          【解决方案4】:

          你已经接近了。您现在的实现是错误的,因为您的条形长度不是len(words) 而是len(words) ** 2,您应该更新每个操作。此外,当需要二维数组时,您正在尝试构建一维数组。所以,试试这个:

          npa = []
          akt = 1
          num_words = len(words)
          with progressbar.ProgressBar(max_value = num_words ** 2) as bar:
              for w2 in words:
                  for w1 in words:
                      npa.append(distance.levenshtein(w1,w2))
                      bar.update(akt)
                      akt = akt + 1
          lev_similarity = -1*np.array(npa).reshape(num_words, num_words)
          

          这样您每次计算距离时都会更新条形图。

          【讨论】:

          • 不一样:ValueError:预期二维数组,得到一维数组:array=[0 -106....]。如果您的数据具有单个特征,则使用 array.reshape(-1, 1) 重塑您的数据,如果它包含单个样本,则使用 array.reshape(1, -1)。
          • @Alex 抱歉,我以为您唯一的问题是进度条,而不是 ValueError。我已更新我的答案以反映这些问题
          • 谢谢。现在我得到AttributeError: 'list' object has no attribute 'reshape',指向lev_similarity = -1*np.array(npa.reshape(num_words, num_words))
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多