Короткий ответ
Единственного правильного решения нет: pipeline можно сделать максимально универсальным (конфигурируемым набором шагов) или специфичным под конкретные данные — выбор зависит от разнообразия источников, частоты изменений схемы и готовности команды поддерживать абстракцию.
Как это работает подробнее
переиспользуемый pipeline обычно строится как последовательность независимых шагов (загрузка → валидация схемы → очистка типов → обработка пропусков/дубликатов → агрегация), каждый из которых можно включать, отключать или настраивать параметрами, а не как монолитная функция с зашитой логикой под один датасет.
Пример кода
Пример на Python
import pandas as pd
def clean_pipeline(df: pd.DataFrame, config: dict) -> pd.DataFrame:
df = df.drop_duplicates(subset=config.get('dedup_key'))
for col, dtype in config.get('dtypes', {}).items():
df[col] = df[col].astype(dtype, errors='ignore')
for col in config.get('required_columns', []):
assert df[col].notna().all(), f'Unexpected nulls in {col}'
return df
config = {'dedup_key': ['order_id'], 'dtypes': {'amount': 'float'}, 'required_columns': ['order_id']}Что использовать на практике
- На практике. полезно явно разделить "общие" шаги (приведение типов, проверка дубликатов по ключу, базовые инварианты) и "специфичные для проекта" шаги (бизнес-логика конкретной метрики), чтобы общая часть переиспользовалась, а специфичная — настраивалась отдельно; конфигурацию стоит выносить в читаемый формат (словарь/YAML), а не хардкодить внутри функций.
- Проверка. такой конфигурируемый pipeline можно прогнать на нескольких разных синтетических таблицах с разными наборами столбцов и проверить, что базовые шаги (дедупликация, проверка на null) срабатывают одинаково, а специфичная логика задаётся только через config.
Подводные камни
- Частые ошибки. делают pipeline настолько гибким и параметризуемым, что его сложнее понять и отладить, чем несколько простых специализированных скриптов; или наоборот — жёстко зашивают предположения одного проекта (названия столбцов, форматы дат) в общий модуль, из-за чего при переносе на другой проект код приходится переписывать, а не конфигурировать.