Как создать параметризованные блокноты Jupyter Notebook с помощью Papermill
Введение
В программировании функции — это способы модульного разделения кода на автономные, организованные и многократно используемые блоки, используемые для выполнения конкретной задачи. Функции обычно принимают входные данные, обрабатывают данные и выводят результат. Некоторые преимущества написания кода в виде функций:
- Улучшить возможность повторного использования кода
- Разбейте проблему на более мелкие решаемые части
- Держите более чистое пространство имен переменных
- Возможность тестировать небольшие части кода изолированно
В этой статье мы рассмотрим, как мы можем параметризовать наш блокнот Jupyter, чтобы он работал как функция.
Подождите, но почему?
Мотивация
Давайте представим, что мы занимаемся недвижимостью, и у пользователей есть вопросы, связанные с продажей недвижимости за последние несколько лет. Мы будем использовать набор данных о ценах на перепродажу жилья в Сингапуре[1], который содержит записи о транзакциях по перепродаже домов Советом по развитию жилищного строительства (HDB). Вот пример набора данных.
Бизнес-пользователям интересно ответить на следующие вопросы для town
Центрального района в период с month
января 2017 г. по декабрь 2021 г.:
- Количество продаж в
month
resale_price
черезmonth
- Распределение
resale_price
по разнымflat_type
Мы импортируем необходимые пакеты, считываем данные и фильтруем данные для правильного подмножества, указанного town
и date
. Имея правильное подмножество данных, мы теперь можем построить соответствующие диаграммы, чтобы ответить на вопросы.
Все сделано! Отчет для town
«Центральной области», запрошенный бизнес-пользователями, готов.
Что делать, если бизнес-пользователи запрашивают ту же информацию для другого town
?
Достаточно просто, давайте найдем и заменим! Мы просто находим все старые значения для town
и заменяем их новыми значениями, запускаем записную книжку и сохраняем копию записной книжки.
Что, если бизнес-пользователи будут запрашивать одну и ту же информацию для каждого town
доступного?
Всего 29 городов; возможно, не стоит использовать ручной метод «найти и заменить» 29 раз! Вот где Papermill[2] пригодится.
Бумажная фабрика
Papermill – это пакет Python с открытым исходным кодом, который параметризирует и запускает Jupyter Notebooks.
Параметризация — это процесс обобщения блока кода, чтобы сделать его пригодным для повторного использования, путем взятия значений из кода и превращения их в параметр этой функции. Вместо того, чтобы параметрировать небольшой блок кода, мы собираемся параметризовать весь блокнот Jupyter. Это позволяет нам легко запускать один и тот же ноутбук с разными параметрами. Давайте погрузимся в пример.
1. Настройка среды
pip install papermill
Это файловая структура проекта:
data
: содержит входные данныеproduct
: хранить копии выполненных Jupyter Notebookstasks
: содержит блокноты Jupyter Notebooktemplate.ipynb
иdriver.ipynb
template.ipynb
: здесь находится код обработки и визуализации данных. Он похож на код, который мы видели ранее.driver.ipynb
: это блокнот, содержащий фактический набор параметров, из которого Papermill вставит ячейку параметров вtemplate.ipynb
, запустит и сохранит копию.
2. Параметризируйте ноутбук
Давайте посмотрим, какие значения в нашем коде можно параметризовать. Мы назовем параметризованный блокнот template.ipynb
. В общем, мы можем параметризовать любые значения, если предвидим их будущие изменения. Простой способ начать — проверить, по каким столбцам фильтруется DataFrame и какие значения жестко закодированы.
df = pd.read_csv('data/resale-flat-prices.csv')
df['date'] = pd.to_datetime(df['month'], format = '%Y-%m')
df = df.loc[(df['town'] == 'CENTRAL AREA') & (df['date'].between('2017-01-01', '2021-12-01'))]
DataFrame фильтруется с помощью town
и date
, поэтому мы можем заменить значения town
и date
переменной вместо того, чтобы жестко кодировать ее. Если мы ожидаем изменения пути к файлу данных, мы также можем параметризовать его.
Вот еще части кода, которые можно параметризовать. Мы жестко закодировали значение town
в заголовке диаграммы, которое мы можем заменить переменной.
sales_over_time = df.groupby('date', as_index = False).agg({'resale_price':'count'}).rename(columns = {'resale_price':'resale_count'}) fig, ax = plt.subplots(figsize = (10, 5)) ax = sns.lineplot(data = sales_over_time, x = 'date', y = 'resale_count') ax.set_xlabel('Month') ax.set_ylabel('Sales Transaction') ax.set_title('Number of Sales Over Time - Central Area') plt.show()
Вот как выглядит код до и после параметризации. Жестко закодированные значения town
и date
заменяются переменными.
# before df = pd.read_csv('data/resale-flat-prices.csv') df['date'] = pd.to_datetime(df['month'], format = '%Y-%m') df = df.loc[(df['town'] == 'CENTRAL AREA') & (df['date'].between('2017-01-01', '2021-12-01'))] # after df = pd.read_csv(input_path) df['date'] = pd.to_datetime(df['month'], format = '%Y-%m') df = df.loc[(df['town'] == town) & (df['date'].between(start_date, end_date))]
Название сюжета также параметризуется с помощью f-строк.
# before .. ax.set_title('Number of Sales Over Time - Central Area') # after .. ax.set_title(f'Number of Sales Over Time - {town.title()}')
Для блокнота были созданы следующие параметры: input_path
, town
, start_date
, end_date
, и вот так теперь выглядит template.ipynb
.
Никакие значения не были присвоены ни одной из переменных input_path
, town
, start_date
, end_date
. Следующая ячейка была бы включена, если бы эта записная книжка использовалась один раз или несколько раз.
# notebook cell
# Parameters
input_path = "../data/resale-flat-prices.csv"
start_date = "2017-01-01"
end_date = "2021-01-01"
town = "CENTRAL AREA"
Перед каждым запуском мы вручную меняли значения параметров в соответствии с запросами бизнес-пользователей.
Однако этот метод не подходит для ситуаций с большим количеством наборов параметров. В нашем случае 29 городов, и невозможно вручную изменить значение town
29 раз. Нам нужен способ автоматической передачи различных наборов параметров в template.ipynb
, и об этом позаботится driver.ipynb
.
3. Создайте driver.ipynb
Вот где происходит волшебство. В целях иллюстрации мы генерируем отчет только для 4 разных городов, создавая словарь параметров для каждого города и передавая его методу .execute_notebook()
Papermill.
# driver.ipynb import papermill as pm
# generate report for each town
towns = ['CENTRAL AREA', 'MARINE PARADE', 'WOODLANDS', 'QUEENSTOWN']
for town in towns:
params = {'input_path': '../data/resale-flat-prices.csv', 'start_date': '2017-01-01', 'end_date': '2021-01-01', 'town': town}
nb_output = pm.execute_notebook('template.ipynb', f'../products/report_{town.title()}.ipynb', parameters = params)
Аргументы для .execute_notebook()
:
input_path
: (str или path) путь к вводу Jupyter Notebook, который мы собираемся выполнить, в нашем случае это будетtemplate.ipynb
.output_path
: (str или path) путь для сохранения выполненного Jupyter Notebook. Мы сохраняем выполненную записную книжку с объединенным названием города.parameters
: (dict) параметры, переданные в Jupyter Notebook вinput_path
.execute_notebook()
делает следующее:
- Находит входной блокнот, т.е.
template.ipynb
2. Вводит параметры в template.ipynb
во время выполнения
3. Запускает template.ipynb
с введенными параметрами
4. Сохраняет копию выполненной записной книжки вместе с выводами ячеек в output_path
4. Запустите driver.ipynb
При выполнении блокнот driver.ipynb
передает разные наборы параметров в template.ipynb
, выполняет template.ipynb
и сохраняет копию выполненных блокнотов для разных наборов параметров в output_path
, определенном в .execute_notebook()
.
На изображении ниже показаны сохраненные выходные блокноты.
Давайте взглянем на одну из сохраненных записных книжек. В report_Central Area.ipynb
мы видим, что Papermill ввел набор параметров в первую ячейку.
Заключение
В этой статье мы мотивировали параметризацию Jupyter Notebook и продемонстрировали пример использования для анализа данных о том, как запустить Papermill через API Python. Сценарии использования Papermill не ограничиваются созданием отчетов. Другие пакеты с открытым исходным кодом, такие как Ploomber, используют Papermill для ввода параметров в ячейки для создания многоразовых конвейеров машинного обучения. Papermill также предлагает выполнение через интерфейс командной строки и позволяет использовать .yaml
file для хранения параметров. Посетите Papermill github для получения дополнительной информации.
- Присоединяйтесь к Medium, чтобы читать больше таких историй
- Следуй за мной, чтобы увидеть больше таких постов
Ссылка
[1] Содержит информацию из Resale Flat Prices, доступ к которой был получен 17 марта 2022 г. по адресуhttps://data.gov.sg/dataset/resale-flat-prices, который доступен в соответствии с условия Сингапурской лицензии на открытые данные версии 1.0https://data.gov.sg/open-data-licence. Разрешено для публичного использования (коммерческого и некоммерческого).
[2] Бумажная фабрика