Python для аналитика: рабочий стек из Jupyter, pandas и графиков
Какие инструменты нужны аналитику в Python: Jupyter, pandas, NumPy и matplotlib, как они связаны и с какого рабочего сценария начать.
Содержание статьи
Аналитику не нужен «весь Python». Нужен небольшой, понятный рабочий стек, который помогает взять данные, проверить их, посчитать показатель и показать вывод. Начнём с связки Jupyter + pandas + NumPy + matplotlib и разберём, где она дополняет SQL и BI, а где только усложняет задачу.
Коротко
Jupyter — рабочая среда для экспериментов и объяснения расчёта. pandas — таблицы и операции над ними. NumPy — численные массивы и функции. matplotlib — базовые графики. Вместе они закрывают большую часть небольших и средних исследовательских задач аналитика.
- Храните исходные данные отдельно от ноутбука и не меняйте их на месте.
- Один ноутбук должен отвечать на один вопрос или исследование.
- Оставляйте рядом с цифрой определение, фильтры и период расчёта.
- SQL лучше использовать для тяжёлой выборки, Python — для исследования и повторяемого анализа.
Из чего состоит стек
Инструменты не конкурируют между собой. SQL достаёт и агрегирует данные ближе к хранилищу. Python помогает быстро проверить гипотезу, соединить небольшой набор файлов, построить нестандартный график или сохранить расчёт в понятном ноутбуке. BI нужен, когда результат должен регулярно смотреть широкий круг людей.
| Инструмент | За что отвечает | Когда открывать |
|---|---|---|
| Jupyter | ячейки кода, текст, таблицы и графики в одном документе | исследование, разбор, обучение, прототип |
| pandas | табличные данные, фильтры, пропуски, группировки и соединения | CSV, выгрузка из SQL, подготовка отчёта |
| NumPy | массивы, численные операции и функции | векторные расчёты, симуляции, работа под капотом pandas |
| matplotlib | контролируемые графики и настройка осей | проверка тренда, распределения, сравнение сегментов |
| SQL / BI | источник данных и регулярная коммуникация результата | большие таблицы, дашборды, мониторинг |
Первый рабочий цикл
Новый ноутбук лучше начинать не с импорта десяти библиотек, а с заголовка, вопроса и условий. Затем загрузи минимальный срез, проверьте форму и типы, сделайте один расчёт и только после этого добавляйте визуализацию. Такой порядок помогает не потеряться в графиках и случайных фильтрах.
# Вопрос: как меняется средний заказ по каналам за июль?
import pandas as pd
import matplotlib.pyplot as plt
orders = pd.read_csv('data/orders.csv', parse_dates=['created_at'])
july = orders.loc[
(orders['created_at'] >= '2026-07-01')
& (orders['created_at'] < '2026-08-01')
& (orders['status'] == 'paid')
].copy()
summary = july.groupby('channel', as_index=False).agg(
orders=('order_id', 'nunique'),
average_order=('revenue', 'mean'),
)
summary.plot.bar(x='channel', y='average_order', legend=False)
plt.show()Ноутбук должен объяснять, а не только считать
Через месяц результатом будут пользоваться не только вы. Подпишите, откуда пришли данные, какая строка считается заказом, почему выбран период и что означает график. Текстовые Markdown-ячейки — часть аналитики, а не украшение. Если расчёт нельзя пересказать без запуска всех ячеек, он плохо подготовлен для передачи.
Код может без ошибок посчитать среднее, DAU или retention. Но только аналитик задаёт знаменатель, временное окно, timezone и правило исключения тестовых пользователей.
- В начале запишите вопрос и единицу анализа.
- После загрузки покажите размер, период и пропуски.
- Перед графиком выведите маленькую итоговую таблицу.
- Не оставляйте в финальном ноутбуке десятки случайных промежуточных экспериментов.
- Сохраните версию исходного файла или ссылку на запрос, из которого он получен.
Когда открыть SQL, а когда Python
Если таблица содержит сотни миллионов событий, не скачивайте её целиком в ноутбук. Сначала отфильтруйте период и агрегируйте данные в SQL, затем передайте в pandas результат, который помещается в память и нужен для исследования. Для регулярного KPI лучше оставить расчёт в SQL/BI, а ноутбук использовать как место проверки и поиска причин. Та же граница на одной задаче, решённой запросом и в pandas, — в разборе что аналитик делает в SQL, а что в Python.
| Задача | Первый инструмент | Почему |
|---|---|---|
| DAU за год по всем событиям | SQL | данные уже находятся в хранилище, важны фильтры и объём |
| Проверить выгрузку и пропуски | pandas | быстрый интерактивный профиль файла |
| Регулярный KPI для команды | BI + SQL | обновление и единое определение |
| Сравнить несколько сценариев и построить нестандартный график | Python | удобно менять расчёт рядом с визуализацией |
Настрой среду так, чтобы её можно было повторить
Рабочий стек начинается не с установки двадцати библиотек, а с понятной среды. Зафиксируйте версию Python, зависимости и способ запуска ноутбука. Если сегодня pandas обновился автоматически, завтра изменится тип или предупреждение, а коллега не сможет повторить результат. Для маленького проекта достаточно requirements.txt, для более долгого — lock-файл и отдельное окружение.
Не смешивайте системный Python, окружение проекта и ядро Jupyter. Проверьте, что notebook действительно использует то окружение, где установлены pandas и NumPy. Сообщение «пакет установлен» ничего не доказывает, если kernel смотрит в другой интерпретатор.
В начале ноутбука выведите версии ключевых библиотек и путь к входным данным. Это выглядит скучно, но превращает случайный запуск в документированный эксперимент. При расследовании расхождения такие две строки часто экономят больше времени, чем повторное чтение всего кода.
import sys
import pandas as pd
import numpy as np
from pathlib import Path
print('python:', sys.version)
print('pandas:', pd.__version__)
print('numpy:', np.__version__)
print('cwd:', Path.cwd())Установленный pandas может оказаться вне ядра ноутбука
В терминале импорт pandas проходит, а ноутбук с июльскими заказами сообщает ModuleNotFoundError. Сначала сравните sys.executable в обоих местах. Эта строка показывает интерпретатор, который действительно выполняет код. Запуск pip сам по себе не гарантирует, что пакет устанавливается туда же: команда может относиться к другому Python. Используйте python -m pip от выбранного интерпретатора, чтобы установка и последующий импорт обращались к одному окружению.
Для небольшого проекта создайте окружение командой python3 -m venv .venv. В macOS и Linux его интерпретатор находится в .venv/bin/python, в Windows — в .venv/Scripts/python.exe. Через этот интерпретатор установи согласованные зависимости проекта. Если интерфейс Jupyter запущен из другой среды, зарегистрируйте ядро командой .venv/bin/python -m ipykernel install --user --name orders-analysis --display-name "Orders analysis". После выбора этого ядра повторно выведите sys.executable в ноутбуке.
Файл requirements.txt со строкой pandas без версии описывает пожелание, а не воспроизводимое окружение. Для проверенной конфигурации зафиксируйте точные версии. python -m pip freeze сохраняет снимок установленных пакетов, включая транзитивные зависимости; выполняйте его в чистой среде проекта, иначе в список попадут случайные инструменты. Храните отдельно короткий перечень прямых зависимостей с объяснением, зачем каждая нужна. Сам каталог .venv передавать коллеге не нужно: его создают заново.
Версии пакетов — лишь часть условий. Укажите версию Python и платформу, особенно если используются бинарные библиотеки. Совпадение freeze не гарантирует идентичного поведения на другой системе; некоторые сборки могут быть недоступны. Проверьте установку и выполнение анализа с нуля в целевом окружении. Для долгого проекта полезен инструмент с lock-файлом, но сначала нужен реально повторённый запуск, а не просто наличие файла с названием lock.
В исходном июльском расчёте достаточно pandas для таблицы и matplotlib для графика; Jupyter и ipykernel обслуживают исследовательскую среду. NumPy становится прямой зависимостью, когда вы сам используете его массивы или случайные числа. Excel потребует подходящего reader, Parquet — движка хранения; scikit-learn не нужен только ради среднего чека. Добавляйте библиотеку под конкретную операцию, чтобы обновление одной необязательной части стека не усложняло передачу простого отчёта.
import sys
from importlib.metadata import version
from pathlib import Path
print('kernel:', sys.executable)
print('python:', sys.version)
for package in ('pandas', 'matplotlib', 'ipykernel'):
print(package, version(package))
print('orders file:', Path('data/orders.csv').resolve())Структура проекта важнее количества библиотек
Для учебного анализа достаточно папок data, notebooks, src и output. Сырые файлы не редактируются, notebook отвечает за исследование и объяснение, а повторяемые функции живут в src. Такой порядок не требует сложной архитектуры, но не даёт смешать загрузку, очистку и презентацию в одной ячейке.
Имена файлов должны говорить о слое и периоде: raw/orders_2026_08.csv, clean/orders.parquet, output/channel_report.csv. Не называйте результат final_final_2.csv. Если файл создаётся кодом, путь к нему должен быть параметром или константой, а не ручным переключателем в середине ноутбука.
Добавьте README с одним рабочим сценарием: как создать окружение, где лежит файл, какой командой запустить notebook и какие контрольные числа ожидать. Документация не обязана быть длинной. Её задача — убрать догадки при первом запуске другим человеком.
| Папка | Назначение |
|---|---|
| data/raw | исходные выгрузки без ручной правки |
| data/clean | типизированные и проверенные слои |
| notebooks | исследование, графики и объяснение |
| src | переиспользуемые функции и проверки |
| output | собранные таблицы и изображения |
Повторяемый расчёт июля должен запускаться без истории ячеек
Ноутбук про средний заказ по каналам подходит для исследования: вы меняете срезы и объясняете наблюдения рядом с таблицей. Когда тот же расчёт нужен за август, скрытые зависимости становятся заметны. Переменная july могла остаться от вчерашнего запуска, путь — указывать на чужую папку, фильтр — зависеть от текущей даты. Первый контроль — перезапустить ядро и выполнить все ячейки сверху вниз на сохранённом входном файле.
Если этот запуск воспроизводится, вынесите устойчивую часть в функцию: она принимает таблицу, начало и конец периода, а возвращает итог по каналам. Внутри не должно быть чтения глобальной переменной или вызова текущего времени. Внешний скрипт отвечает за загрузку файла и сохранение результата, ноутбук — за объяснение и график. Так в src появляется проверяемый расчёт, а не вторая копия большого ноутбука со слегка изменённой датой.
Пути тоже относятся к входам. Относительный data/orders.csv вычисляется от текущего рабочего каталога, который у терминала и Jupyter может различаться. Передавайте путь явным параметром запуска либо договоритесь запускать проект из корня и проверяйте разрешённый абсолютный путь. Не исправляйте каждую ошибку очередной командой chdir в середине ноутбука. При передаче результата сохраните имя и хэш выгрузки, чтобы коллега мог отличить смену данных от изменения кода.
Контрольный набор для функции должен отражать вопрос отчёта. Добавьте оплаченный заказ в июле, неоплаченный в июле и оплаченный ровно в начале августа. Первый входит в итог, два других — нет. Если канал неизвестен, группа должна остаться видимой, поэтому в коде задан dropna=False. Функция предполагает уже проверенную таблицу с одной строкой на заказ и revenue без пропусков; нарушения этих условий проверяются при загрузке, а не прячутся внутри среднего.
Скрипт нужен, когда расчёт должен повторяться по расписанию, принимать параметры или останавливать процесс понятной ошибкой без ручного вмешательства. Сам факт большого числа ячеек ещё не требует миграции. Исследовательские диаграммы могут остаться в ноутбуке, если регулярно запускаемая функция одна и та же. Сохраните её версию вместе с итоговой таблицей и периодом: тогда изменение июльского результата можно разобрать по входу и коду, а не по памяти автора.
import pandas as pd
def channel_summary(orders, start, end):
selected = orders.loc[
orders['created_at'].ge(start) & orders['created_at'].lt(end)
& orders['status'].eq('paid')
]
return selected.groupby('channel', dropna=False, as_index=False).agg(
orders=('order_id', 'nunique'), average_order=('revenue', 'mean'),
)
fixture = pd.DataFrame({
'order_id': [101, 102, 103], 'channel': ['organic'] * 3,
'created_at': pd.to_datetime(['2026-07-01', '2026-07-02', '2026-08-01']),
'status': ['paid', 'pending', 'paid'], 'revenue': [1200, 800, 450],
})
result = channel_summary(fixture, pd.Timestamp('2026-07-01'), pd.Timestamp('2026-08-01'))
assert result['orders'].tolist() == [1]
assert result['average_order'].tolist() == [1200.0]Отладка начинается с маленького среза
Когда расчёт падает на большом файле, сначала воспроизведите проблему на небольшом срезе. Сохраните строки вокруг неверного значения, а не весь источник. Маленькая фикстура быстрее читается, легче прикладывается к issue и помогает написать regression-тест после исправления.
Разделяйте техническую и методологическую ошибку. KeyError означает, что код не нашёл колонку. Успешный расчёт с неправильным знаменателем — уже методологическая ошибка, и её не поймает Python. Поэтому в каждом рабочем ноутбуке должны быть и проверки схемы, и sanity-check на смысловые значения.
График используйте как диагностический инструмент, а не только как финальную иллюстрацию. Линия по дням помогает увидеть пропущенный период, bars по каналам — unknown, а таблица квантилей — неожиданный хвост. Визуализация в отладке часто быстрее, чем просмотр сотен строк.
Небольшой воспроизводимый пример помогает и вам, и коллеге, который будет разбирать ошибку. Он превращает «у меня странная цифра» в конкретное правило и вход.
Первый проект аналитика: от вопроса до memo
Для практики возьмите вопрос «почему изменилась выручка по каналам». Получите ограниченный период через SQL или CSV, проверьте схему в pandas, соберите revenue, orders и buyers по каналу, затем разбейте общий результат на новые и вернувшиеся аккаунты. Один вопрос даст достаточно материала для фильтра, groupby, merge, графика и проверки.
В финальном memo не перечисляйте функции pandas. Напишите, какой сегмент изменился, насколько велика база, что вы проверили и какое действие предлагаете. Код нужен, чтобы сделать вывод воспроизводимым, а не чтобы заменить вывод списком методов.
После первого проекта добавьте тест на контрольный DataFrame и ссылку на соседнюю SQL-статью. Так рабочий стек становится траекторией: Python помогает исследовать, SQL — считать ближе к источнику, а визуализация — объяснять решение команде.
- Зафиксировать версии и окружение.
- Разделить raw, clean, notebook и output.
- Получить маленький воспроизводимый срез.
- Добавить проверки схемы и смысла результата.
- Закончить memo с действием, а не перечнем методов.
Материалы по теме

Как тестировать аналитические расчёты на Python и pandas
Практический гайд по тестам для аналитика: проверить метрики на маленьком датасете, поймать регрессию и защитить расчёт от тихих изменений.

Как ускорить pandas: память, типы и обработка больших файлов
Что делать, если pandas медленно работает или не помещает файл в память: категории, downcast, chunksize, Parquet и контроль размера данных.

Pandas apply и векторизация: как писать быстрее и понятнее
Когда использовать apply, почему векторные операции быстрее и как переписать медленный построчный расчёт в pandas.