【问题标题】:How can you show progress bar while iterating over a pandas dataframe如何在遍历熊猫数据框时显示进度条
【发布时间】:2020-06-19 20:07:38
【问题描述】:

我正在尝试迭代具有接近一百万个条目的 Pandas 数据框。我正在使用 for 循环来迭代它们。以下面的代码为例

import pandas as pd 
import os 
from requests_html import HTMLSession
from tqdm import tqdm
import time


df = pd.read_csv(os.getcwd()+'/test-urls.csv')
df = df.drop('Unnamed: 0', axis=1 )

new_df = pd.DataFrame(columns = ['pid', 'orig_url', 'hosted_url'])
refused_df = pd.DataFrame(columns = ['pid', 'refused_url'])

tic = time.time()

for idx, row in df.iterrows():

    img_id = row['pid']
    url = row['image_url']

    #Let's do scrapping 
    session = HTMLSession()
    r  = session.get(url)
    r.html.render(sleep=1, keep_page=True, scrolldown=1)

    count = 0 
    link_vals =  r.html.find('.zoomable')

    if len(link_vals) != 0 : 
        attrs = link_vals[0].attrs
        # print(attrs['src'])  
        embed_link = attrs['src']

    else: 
        while count <=7:
            link_vals =  r.html.find('.zoomable')
             count += 1
        else:
             print('Link refused connection for 7 tries. Adding URL to Refused URLs Data Frame')
            ref_val = [img_id,URL]
            len_ref = len(refused_df)
            refused_df.loc[len_ref] = ref_val
            print('Refused URL added')
            continue
    print('Got 1 link')

#Append scraped data to new_df
    len_df = len(new_df)
    append_value = [img_id,url, embed_link]
    new_df.loc[len_df] = append_value

我想知道如何使用进度条来直观地表示我已经走了多远。我将不胜感激。如果您需要任何澄清,请告诉我。

【问题讨论】:

  • 你想做什么?如果您的索引是有序索引/形状,您可以只打印一个百分比。我同意 Robbwh 的观点,如果你使用 iterrows,你可能做错了。
  • 我正在尝试从 URL 中抓取一些数据。我添加了上面的代码。如果您认为我可以进行任何更改,请告诉我

标签: python pandas progress-bar tqdm


【解决方案1】:

你可以试试TQDM

from tqdm import tqdm
for idx, row in tqdm(df.iterrows()):
      do something

这主要用于命令行进度条。如果您正在寻找更多的 GUI,还有其他解决方案。 PySimpleGUI 浮现在脑海中,但肯定要复杂一些。

【讨论】:

    【解决方案2】:

    会发表评论,但您可能需要进度条的原因是因为 iterrows() 是在 pandas 中进行操作的一种缓慢方法,因此需要很长时间。

    我建议你使用 apply/避免使用 iterrows()。

    如果您想继续使用 iterrows,只需包含一个计数到行数的计数器,df.shape[0]

    【讨论】:

    • 我正在尝试从 URL 中抓取一些数据。我添加了上面的代码。如果您认为我可以进行任何更改,请告诉我
    • 这并不像“应用比 iterrows 快”那么简单,但它的方向是正确的。 stackoverflow.com/questions/24870953/…
    • @sanster9292 啊,我以为您主要是在数据帧操作中进行操作。如果性能非常慢,我会考虑找到一种方法来并行化这些操作,尽管我在这方面的经验有限,这可能是一个愚蠢的建议。祝你好运。
    • @robbwh 速度很好我只是想直观地表示我走了多远,因为我将爬到接近 700k 的网址
    【解决方案3】:

    PySimpleGUI 使解决问题尽可能简单,假设您提前知道列表中的项目。不确定的进度表是可能的,但稍微复杂一些。

    循环之前不需要设置。您不需要制作特殊的迭代器。您唯一需要做的就是在循环中添加 1 行代码。

    在您的循环中添加对 - one_line_progress_meter 的调用。这个名字总结了它是什么。将此调用添加到循环的顶部,底部,没关系...只需将其添加到循环的地方即可。

    您传递的参数有 4 个:

    • 要放在仪表上的标题(任何字符串都可以)
    • 你现在在哪里 - 当前计数器
    • 最大计数器值是多少
    • 一个“键”——一个唯一的字符串、数字,任何你想要的东西。

    这是一个循环遍历整数列表以进行演示的循环。

    import PySimpleGUI as sg
    
    items = list(range(1000))
    total_items = len(items)
    for index, item in enumerate(items):
    
        sg.one_line_progress_meter('My meter', index+1, total_items, 'my meter' )
    
    

    列表迭代代码将是您的循环代码。您将要添加的代码行是这样的:

    sg.one_line_progress_meter('My meter', index+1, total_items, 'my meter' )

    这行代码将显示下面的窗口。它包含统计信息,例如您已运行循环多长时间以及您需要多长时间的估计。

    【讨论】:

      【解决方案4】:

      如何在熊猫应用中做到这一点? 我这样做

      def some_func(a,b):
         global index
         some function involve a and b
         index+=1
         sg.one_line_progress_meter('My meter', index, len(df), 'my meter' )
         return c
      
      index=0
      df['c'] = df[['a','b']].apply(lambda : some_func(*x),axis=1)
      

      【讨论】:

      • 如果您有新问题,请点击 按钮提出问题。如果有助于提供上下文,请包含指向此问题的链接。 - From Review
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-20
      • 1970-01-01
      • 2021-11-09
      • 2019-05-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多