Статьи
November 14, 2022

Пишем прогресс-бары при помощи tqdm

В переводе с арабского tqdm (taqadum) означает прогресс; библиотека с таким названием используется как раз для создания индикаторов прогресса. Просто оберните любой итерируемый объект в функцию – tqdm(iterable) – и готово.

Таким образом можно создать прогресс-бары для обработки данных, моделей машинного обучения или загрузки данных из интернета. Но сначала нужно установить библиотеку:

pip install tqdm

А теперь без лишних разговоров берите копируйте код ниже, запускайте у себя и любуйтесь. Библиотека tqdm помимо, собственно, самого прогресс-бара, показывает также количество итераций, время, затраченное на выполнение цикла, и частоту итераций в секунду. Видели ли вы что-то прекраснее сегодня?

from tqdm import tqdm

for i in tqdm(range(10000)):
    pass
100%|🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩| 10000/10000 [00:00<00:00, 1764759.54it/s]

Ладно, давайте теперь научимся настраивать наши индикаторы и использовать при обработке датафреймов. Заодно узнаем о некоторых дополнительных фичах библиотеки.

tqdm и функции

В примере ниже мы создали функцию fun, которая принимает целое число x и исполняется с задержкой в x секунд. Потом мы обернули tqdm вокруг функции range, которая будет запускать цикл на 10 итераций. Для выполнения первой итерации потребуется 0 секунд. Вторая итерация займет 1 секунду, и так далее. Для завершения цикла потребовалось 45 секунд, и мы при этом видим анимированный индикатор выполнения.

from tqdm import trange, tqdm
from time import sleep

# функция с задержкой исполнения
def fun(x):
    sleep(x)
    return x

    # цикл с прогресс-баром
for i in tqdm(range(10)):
    fun(i)
100%|██████████| 10/10 [00:45<00:00, 4.51s/it]

Ну офигенно же!

tqdm.notebook в списке

А здесь будем использовать модуль tqdm.notebook для отображения прогресс-баров в Jupyter Notebook с помощью виджетов Ipython.

Сначала создаём простой список различных цветов. Затем с помощью цикла выведем их названия одно за другим с задержкой в одну секунду. Заворачиваем список в модуль, и радуемся анимированному индикатору.

from tqdm.notebook import tqdm

colors = ["Blue", "Green", "Yellow", "White", "Gray", "Black"]
for x in tqdm(colors):
    sleep(1)
    print(x)

Несколько индикаторов выполнения

С помощью вложенных циклов напишем несколько прогресс-баров, имитирующих визуализацию хода обучения модели машинного обучения.

  • trange – это комбинация из функции tqdm, обёрнутой вокруг функции range.
  • Внешний цикл будет выполняться за 10 итераций с задержкой 0,01 сек.
  • desc используется для обозначения индикатора выполнения.
  • Внутренний цикл будет выполняться за 10 000 итераций с задержкой 0,001 сек.

Посмотрите, насколько круто выглядит анимация! Скопируйте код ниже, подшаманьте над ним немного на своё усмотрение и запустите.

from tqdm.notebook import trange

for i in trange(10, desc="Traning Model on 10 Epochs"):
    sleep(0.01)
    for x in trange(10000, desc=f"Epoch {i}"):
        sleep(0.001)

tqdm для Data Science

В этой части мы соединим функционал библиотек tqdm и pandas и с помощью progress_apply применим функцию к датафрейму, чтобы добавить прогресс-бар.

Загружаем датасет

Сначала загрузим набор данных по бронированию отелей с Kaggle. Затем отобразим пять верхних строк датафрейма.

Набор содержит 119390 строк с данными о бронирований номеров в городских гостиницах и курортных отелях в период с 1 июля 2015 года по 31 августа 2017 года, включая фактически прибывшие и отмененные бронирования.

import pandas as pd
df = pd.read_csv("hotel_booking.csv")
df.head().to_frame()

Применение функции с помощью tqdm

Создадим новый столбец user_name с именами клиентов.

  • функция tqdm.pandas нужна для инициализации прогресс-бара в датафрейме. Добавим к нему название Processing the name colum.
  • Функция user_name приводит строку к нижнему регистру и заменяет пробелы на "-".
  • Применим функцию к датафрейму с помощью .progress_apply(). Она аналогична функции apply(). А для функции map() можно использовать .progress_map().
  • Отображаем три верхние строки нашего набора данных
# задаём имя прогресс-бару
tqdm.pandas(desc="Processing the name column")

# преобразование текста
def user_name(text):   
  return text.lower().replace(" ","-")

# применение функции к столбцу
df["user_name"] = df["name"].progress_apply(user_name)

# вывод первых трёх строк
df.head(3)

Утилита для параллельной обработки

Библиотека tqdm нужна не только для написания прогресс-баров для циклов, в ней есть также утилиты для параллельной обработки, например, функция tqdm.contrib.concurrent.

Давайте попробуем извлечь доменные имена из адресов электронной почты в столбце email.

  • Импортируем process_map из tqdm.contrib.concurrent.
  • С помощью функции provider_extraction разделим текст сначала по знаку "@", затем по знаку ".".
  • Применяем функцию process_map к столбцу email. В качестве параметров укажем max_worker, равный 8, основываясь на количестве ядер процессора, и зададим chunksize, равный 64.
  • Добавим имя прогресс-бара и настроим его цвет — пусть будет зелёный.
  • Выводим первые пять строк столбца email_provider.
from tqdm.contrib.concurrent import process_map

# функция для извлечения email
def provider_extraction(email):
    return email.split("@")[1].split(".")[0]

# применения функции к столбцу
df["email_provider"] = process_map(
    provider_extraction,
    df["email"],
    max_workers=8,
    chunksize=64,
    desc="Extracting Email provider",
    colour='green'
)

df["email_provider"].head().to_frame()

Мы поэкспериментировали с библиотекой tqdm, но она, на самом деле, может гораздо больше. Почитайте документацию и узнаете о других её возможностях.

PythonTalk в Telegram

Чат PythonTalk в Telegram

Предложить материал | Поддержать канал

Источник: KDNuggets
Перевод и адаптация: Екатерина Прохорова