Ответ 1
Существует много способов организовать проект исследования ipython. Я управляю командой из 5 Ученых Данных и 3 Инженеров Данных, и я нашел, что эти советы хорошо работают для нашего usecase:
Это краткое изложение моей беседы PyData London:
http://www.slideshare.net/vladimirkazantsev/clean-code-in-jupyter-notebook
1. Создание общей (многопроектной) библиотеки utils
Скорее всего, вам придется повторно использовать/повторять код в разных исследовательских проектах. Начните реорганизовывать эти вещи в пакет "common utils". Сделайте файл setup.py, надавите модуль на github (или аналогичный), чтобы члены команды могли "установить" его из VCS.
Примерами функциональных возможностей для ввода являются:
- Функции хранилища данных или хранения данных
- общие функции построения
- повторно используемые методы математики/статистики
2. Разделите свой жирный мастер-блокнот на меньшие ноутбуки
По моему опыту, хорошая длина файла с кодом (любой язык) - это всего лишь несколько экранов (100-400 строк). Jupyter Notebook по-прежнему является исходным файлом, но с выходом! Чтение ноутбука с 20 + клетками очень сложно. Мне нравятся мои ноутбуки с максимальным размером 4-10 ячеек.
В идеале у каждого ноутбука должен быть один "триплет" гипотез-данных-выводов.
Пример разделения ноутбука:
1_data_preparation.ipynb
2_data_validation.ipynb
3_exploratory_plotting.ipynb
4_simple_linear_model.ipynb
5_hierarchical_model.ipynb
playground.ipynb
Сохраните вывод 1_data_preparation.ipynb, чтобы выбрать df.to_pickle('clean_data.pkl')
, csv или быстрый DB и использовать pd.read_pickle("clean_data.pkl")
в верхней части каждого ноутбука.
3. Это не Python - это IPython Notebook
Что делает ноутбук уникальным, это ячейки. Используйте их хорошо. Каждая ячейка должна быть триплетной "идея-исполнение-вывод". Если ячейка ничего не выводит - соединитесь со следующей ячейкой. Импорт ячейки не должен выводить ничего - это ожидаемый результат для него.
Если ячейка имеет несколько выходов - возможно, стоит ее разделить.
Скрытие импорта может быть или не быть хорошей идеей:
from myimports import *
Ваш читатель может захотеть выяснить, что именно вы импортируете, чтобы использовать тот же материал для своих исследований. Поэтому используйте с осторожностью. Однако мы используем его для pandas, numpy, matplotlib, sql
.
Скрытие "секретного соуса" в /helpers/model.py плохо:
myutil.fit_model_and_calculate(df)
Это может спасти вас при вводе текста, и вы удалите дубликат кода, но вашему соавтору придется открыть другой файл, чтобы выяснить, что происходит. К сожалению, ноутбук (jupyter) является довольно негибкой и базовой средой, но вы все равно не хотите, чтобы ваш читатель оставил его для каждой части кода. Надеюсь, что в будущем IDE улучшится, но пока сохранить "секретный соус" внутри ноутбука. Хотя "скучные и очевидные утилиты" - везде, где вы считаете нужным. DRY все еще применяется - вам нужно найти баланс.
Это не должно мешать вам упаковывать повторно используемый код в функции или даже небольшие классы. Но "квартира лучше, чем вложенная".
4. Держите ноутбуки в чистоте
Вы должны иметь возможность "reset и запустить все" в любой момент времени.
Каждый повторный запуск должен быть быстрым! Это означает, что вам, возможно, придется инвестировать в написание некоторых функций кеширования. Может быть, вы даже захотите поместить их в свой модуль "common utils".
Каждая ячейка должна выполняться несколько раз, без необходимости повторной инициализации ноутбука. Это экономит ваше время и повышает надежность кода. Но это может зависеть от состояния, созданного предыдущими ячейками. Создание каждой ячейки, полностью независимой от вышеуказанных ячеек, является анти-шаблоном, ИМО.
После того, как вы закончите исследование - вы не сделали с записной книжкой. Рефакторинг.
5. Создайте модуль проекта, но будьте очень избирательным
Если вы продолжаете использовать функцию построения графиков или аналитики, выполните ее рефакторинг в этом модуле. Но, по моему опыту, люди ожидают читать и понимать ноутбук, не открывая несколько подмодулей. Таким образом, назначение ваших подпрограмм хорошо еще более важно, по сравнению с обычным Python.
"Чистый код читается как хорошо написанная проза" Грэди Буч (разработчик UML)
6. Сервер узла Jupyter в облаке для всей команды
У вас будет одна среда, поэтому каждый может быстро просмотреть и проверить исследования без необходимости соответствовать среде (хотя conda делает это довольно легко).
И вы можете настроить значения по умолчанию, такие как стиль/цвета mpl, и сделать matplot lib inline, по умолчанию:
В ~/.ipython/profile_default/ipython_config.py
Добавить строку c.InteractiveShellApp.matplotlib = 'inline'
7. (экспериментальная идея) Запустите ноутбук из другого ноутбука с различными параметрами
Довольно часто вы можете повторно запустить весь ноутбук, но с другими входными параметрами.
Для этого вы можете структурировать свой исследовательский ноутбук следующим образом: Поместите params словарь в первую ячейку из исходной записной книжки.
params = dict(platform='iOS',
start_date='2016-05-01',
retention=7)
df = get_data(params ..)
do_analysis(params ..)
И в другом (более высоком логическом уровне) ноутбуке выполните его с помощью этой функции:
def run_notebook(nbfile, **kwargs):
"""
example:
run_notebook('report.ipynb', platform='google_play', start_date='2016-06-10')
"""
def read_notebook(nbfile):
if not nbfile.endswith('.ipynb'):
nbfile += '.ipynb'
with io.open(nbfile) as f:
nb = nbformat.read(f, as_version=4)
return nb
ip = get_ipython()
gl = ip.ns_table['user_global']
gl['params'] = None
arguments_in_original_state = True
for cell in read_notebook(nbfile).cells:
if cell.cell_type != 'code':
continue
ip.run_cell(cell.source)
if arguments_in_original_state and type(gl['params']) == dict:
gl['params'].update(kwargs)
arguments_in_original_state = False
Является ли этот "шаблон дизайна" полезным, пока еще не видно. У нас был некоторый успех - по крайней мере, мы прекратили дублирование ноутбуков только для изменения нескольких входов.
Рефакторинг ноутбука в класс или модуль прерывает быстрый цикл обратной связи "idea-execute-output", который предоставляют ячейки. И, ИМХО, не "ipythonic"..
8. Напишите (единичные) тесты для общей библиотеки в блокнотах и запустите с py.test
Существует плагин для py.test, который может обнаруживать и запускать тесты внутри ноутбуков!