MiddleData Analyst > SQL и данные > SQL
Короткий ответ Нужно сделать LEFT JOIN от полного списка дат периода (сгенерированного или из отдельной календарной таблицы) к агрегированным по дням данным и отобрать те даты, где после соединения не нашлось ни одной строки событий (COUNT(event) = 0 или event_id IS NULL). Как это работает подробнее если просто сделать SELECT DISTINCT date FROM events, пропущенные дни физически отсутствуют в данных и их невозможно «увидеть» — нужна внешняя точка отсчёта (полный список ожидаемых дат), от которой можно оттолкнуться через LEFT JOIN, чтобы явно выявить даты без единой строки в основной таблице. Пример кода Что использовать на практике Практика. такую проверку целесообразно делать частью регулярного мониторинга качества данных (data quality) — например, ежедневная автоматическая проверка «за последние 24 часа данные точно поступили» помогает поймать сбой в пайплайне до того, как искажённый отчёт увидит бизнес. Проверка. Проверка: для каждой найденной «пустой» даты проверить логи загрузки данных (ETL) за этот день,
calendar-tabledata-quality
JuniorData Analyst > SQL и данные > Статистика и теория вероятностей
Короткий ответ Дубликаты обычно ищут через GROUP BY по ключевым полям с HAVING COUNT(*) > 1, либо через оконную функцию ROW_NUMBER() для более гибкого определения «что считать дублем». Как это работает подробнее GROUP BY + HAVING COUNT(*) > 1 группирует строки по выбранным колонкам и оставляет только те группы, где больше одной строки — это и есть дубликаты по этим колонкам. ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...) присваивает номер строкам внутри группы, что удобно для выбора «оставить только первую запись». Пример кода Что использовать на практике На практике: перед поиском дублей нужно явно решить, что считается дублем: полное совпадение всех полей, или совпадение по бизнес-ключу (например, email) при разных ID. Часто дубли возникают из-за повторной отправки формы, сбоя интеграции или отсутствия уникального ограничения в таблице — стоит не только почистить данные, но и найти источник проблемы. Полезно также проверять, не возникают ли дубли систематически в определённый период (например, после сбоя
data-qualityduplicates
JuniorData Analyst > SQL и данные > Python для анализа данных
Короткий ответ Дубликаты находят через df.duplicated(), которая возвращает True для повторяющихся строк, а удаляют через df.drop_duplicates(). Как это работает подробнее duplicated() по умолчанию сравнивает все столбцы и помечает True для всех повторных вхождений строки, кроме первого (keep='first'); drop_duplicates() использует ту же логику и возвращает DataFrame без повторов. Пример кода Что использовать на практике На практике: перед удалением полезно посчитать df.duplicated().sum(), чтобы понять масштаб проблемы, и посмотреть на сами дубликаты через df[df.duplicated()], чтобы убедиться, что это действительно ошибка, а не легитимные одинаковые записи (например, два одинаковых заказа в один день — если они действительно разные события). Проверка: duplicated().sum() равен 1, а итоговый DataFrame содержит 3 строки вместо исходных 4. Подводные камни Частые ошибки: удаляют дубликаты сразу без анализа причины их появления (повторная загрузка файла, джойн с размножением), из-за чего настоящая причина ошибки остаё
data-qualityduplicates
JuniorData Analyst > SQL и данные > Python для анализа данных
Короткий ответ Количество пропусков по столбцам получают через df.isna().sum(), а долю — разделив на df.shape[0] или умножив на 100 для процентов. Как это работает подробнее isna() возвращает DataFrame той же формы из True/False, где True означает пропуск (NaN, None, NaT); sum() по умолчанию считает по столбцам (axis=0), складывая True как 1. Пример кода Что использовать на практике На практике: долю пропусков полезно смотреть именно в процентах и сортировать по убыванию, чтобы сразу увидеть самые проблемные столбцы; также стоит проверить isna().sum(axis=1), чтобы понять, есть ли строки с массовыми пропусками сразу по многим полям. Проверка: для столбца 'a' ожидается 33.3%, для 'b' — 66.7%, что соответствует количеству None в исходных данных. Подводные камни Частые ошибки: считают df.isnull().sum() одинаковым для всех типов "пропусков", хотя пустая строка '' или строка "N/A" не распознаются как NaN и не попадут в счёт без предварительной нормализации значений; делают выводы о пропусках только по общему числу
data-qualitymissing-data
MiddleDevOps Engineer > Контейнеры и доставка > Процессы Linux
Короткий ответ Сначала находят процесс через top/htop или ps aux --sort=-%cpu/-%mem, проверяют его роль (сервис, дочерний воркер, однократная задача) командами ps -o ppid,cmd и systemctl status, затем останавливают максимально безопасным способом: через штатный механизм сервиса (systemctl restart) или SIGTERM с ожиданием, а не сразу SIGKILL. Как это работает подробнее Высокое потребление CPU или памяти может быть симптомом, а не причиной: например, утечка памяти в коде приложения, бесконечный цикл из-за некорректных входных данных, либо нормальная, но временная фоновая задача (переиндексация, компакция); разница принципиальна, потому что в первом случае процесс нужно останавливать и чинить код, а во втором — дождаться завершения или перенести на менее загрученное время. Пример кода Что использовать на практике Практика. перед остановкой стоит снять диагностические данные (jstack/py-spy/perf top в зависимости от рантайма, либо хотя бы strace -p для короткого среза системных вызовов) — это может быть единственн
cpulinux
SeniorPython Developer > Основы Python > Декораторы
Короткий ответ Такой декоратор строится как фабрика декораторов с тремя уровнями вложенности: внешняя функция принимает параметры, средняя — декорируемую функцию, а самая внутренняя обёртка выполняет работу. Параметры попадают в обёртку через замыкание. Как это работает подробнее Три уровня. Обычный декоратор имеет два уровня, а параметризованный — три, потому что параметры должны «дойти» до внутренних функций через замыкание. Синтаксис. Запись @decorator(params) означает, что сначала вызывается decorator(params), возвращающая декоратор, который затем применяется к функции: func = decorator(params)(func). Роли функций. Внешняя функция принимает и запоминает параметры, средний уровень принимает декорируемую функцию, а внутренний wrapper работает при вызове. Фабрика декораторов. Паттерн удобен, когда нужна одна и та же логика обёртки, применяемая с разными настройками. Пример кода Что использовать на практике Параметризация. Используй фабрику декораторов, когда одна и та же обёртка нужна с разными значениями на
argumentsclosures
MiddlePython Developer > Основы Python > Декораторы и кэширование
Короткий ответ Декоратор с параметрами реализуется как функция, принимающая аргументы конфигурации и возвращающая настоящий декоратор — функцию одного аргумента (саму декорируемую функцию), то есть добавляется дополнительный уровень вложенности функций. Как это работает подробнее @retry(times=3) сначала вызывает retry(times=3), которая должна вернуть обычный декоратор; этот декоратор возвращает wrapper, использующий захваченное через closure значение times при каждом вызове. Пример кода Что использовать на практике Практика. Паттерн применяется для настраиваемого поведения: число повторов, таймаут, разрешённые роли для проверки доступа. Важно пробрасывать functools.wraps на самом внутреннем wrapper. Подводные камни Риски. Путают уровни вложенности и забывают один уровень функций; не учитывают, что аргументы декоратора вычисляются один раз при импорте модуля, а не при каждом вызове декорированной функции.
cachingdecorators
MiddleData Analyst > SQL и данные > SQL
Короткий ответ Нужно для каждого клиента определить месяц первой покупки (когорту), затем для каждой его покупки посчитать «номер месяца жизни» относительно когорты, и сгруппировать по когорте и номеру месяца, посчитав количество уникальных активных клиентов. Как это работает подробнее шаг 1 — CTE с MIN(order_date) по клиенту для определения когорты; шаг 2 — присоединение этой когорты к каждой покупке и вычисление разницы в месяцах между покупкой и датой когорты (например, через DATE_PART или DATE_DIFF в зависимости от диалекта); шаг 3 — GROUP BY cohort_month, month_number с COUNT(DISTINCT customer_id). Пример кода Что использовать на практике удержание обычно представляют как таблицу «когорта × номер месяца» с процентом от исходного размера когорты (месяц 0 = 100%). Важно явно решить, что считается «активностью» — любая покупка, определённое действие, вход в приложение — и зафиксировать это определение, так как оно сильно влияет на итоговые цифры. Проверка: для month_number = 0 количество активных клиентов д
cohort-analysiscte
MiddleData Analyst > SQL и данные > SQL
Короткий ответ Нужно сначала для каждого пользователя определить дату первой активности (через MIN(event_date) в CTE), затем в основном запросе помечать событие как «новый пользователь», если его дата совпадает с датой первой активности, и как «вернувшийся» — если не совпадает, и сгруппировать по дате и этой метке. Как это работает подробнее сравнение event_date = first_seen_date для каждой строки активности однозначно классифицирует её на «первый визит» (новый пользователь в этот день) или «повторный визит» (вернувшийся пользователь); агрегация COUNT(DISTINCT user_id) по дате и метке даёт обе метрики за один проход по данным. Пример кода Что использовать на практике Практика. важно явно договориться об определении «нового» и «вернувшегося» пользователя относительно выбранного события — активность в приложении, покупка, регистрация — разные определения дают разные абсолютные числа, хотя общая логика расчёта одна и та же. Проверка. Проверка: new_users, просуммированные по всем дням, должны равняться общему чис
conditional-aggregationcount-distinct
JuniorPython Developer > Основы Python > Code review
Короткий ответ Описание PR должно коротко отвечать на вопросы «что изменилось и зачем», «как это проверить» и «на что обратить внимание», а не просто дублировать название задачи. Как это работает подробнее Хорошее описание экономит время ревьюера: он сразу понимает контекст изменения, не читая всю историю переписки в таск-трекере. Обычно в описание включают ссылку на задачу, краткое резюме изменений, список затронутых мест и шаги проверки (как запустить, что проверить вручную, если это не покрыто тестами). Описание фактически заменяет собой короткую устную презентацию изменения, которую иначе пришлось бы делать лично. Пример кода Что использовать на практике Практика. Если PR большой или затрагивает несколько независимых вещей, стоит явно перечислить их по пунктам — это помогает ревьюеру распределить внимание и не пропустить менее очевидные части диффа. Скриншоты или примеры запросов/ответов полезны для изменений в API или UI, а ссылка на задачу в трекере — для тех, кому нужен более широкий бизнес-контекст. П
code-reviewdocumentation