Pandas & NumPy Academy · Урок

Настройка проекта и загрузка данных

Определите цели проекта, загрузите данные из CSV и базы SQLite, объедините источники и выполните полный аудит объединённого набора данных

Урок 1 из 413 шагов

«Настройка проекта и загрузка данных» — бесплатный урок Pandas & NumPy Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Pandas & NumPy Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Pandas & NumPy Academy содержит 4 уроков всего.

Цель итогового проекта

В этом итоговом проекте Вы объедините все навыки курса — NumPy, Pandas, визуализацию, статистическое тестирование, подключение к базам данных и проектирование конвейеров — в единый сквозной рабочий процесс. Проект имитирует реальную задачу аналитика: загрузить исходные данные из двух источников (CSV-файла и таблицы базы данных), объединить их, проверить качество данных, рассчитать расширенные KPI, визуализировать тенденции и экспортировать готовый отчёт. Это отражает повседневную работу профессиональных аналитиков данных.

Определение целей проекта и KPI

Прежде чем написать первую строку кода, определите цели проекта и ключевые показатели эффективности (KPI), которые Вы будете рассчитывать. Зафиксируйте: на какой бизнес-вопрос Вы отвечаете? Какие источники данных доступны? Какие форматы вывода необходимы? Для этого итогового проекта: проанализировать ежемесячную динамику выручки по категориям товаров, рассчитать удержание по когортам, определить регионы-лидеры по маржинальности и экспортировать отчёт с визуализациями. Чёткая цель предотвращает неконтролируемое расширение задачи и помогает сосредоточить конвейер.

# Project configuration — define goals upfront
CONFIG = {
    'csv_path': 'data/orders_2024.csv',
    'db_url': 'sqlite:///customer_db.sqlite',
    'db_table': 'customers',
    'output_dir': 'output/',
    'report_path': 'output/report.md',
    'analysis_year': 2024,
    'top_n_regions': 5,
    'rolling_window_days': 30
}

print('Project config loaded.')
print('Target KPIs: monthly revenue, cohort retention, top regions by margin')

Загрузка данных из CSV

Загрузите CSV с явным указанием аргументов dtype и parse_dates, чтобы избежать ошибок автоматического определения типов. В реальном проекте CSV мог быть экспортирован другой системой с иными соглашениями, поэтому при необходимости задайте encoding, sep и thousands. Сразу проверьте shape, dtypes и head(), чтобы убедиться в корректности загрузки до выполнения каких-либо преобразований. Эта первичная проверка часто выявляет проблемы с кодировкой, лишние строки заголовка или неожиданные названия столбцов.

import pandas as pd

df_orders = pd.read_csv(
    'data/orders_2024.csv',
    dtype={
        'order_id': 'int32',
        'customer_id': 'int32',
        'product_id': 'int32',
        'quantity': 'int16',
        'unit_price': 'float32',
        'region': 'category',
        'category': 'category'
    },
    parse_dates=['order_date'],
    encoding='utf-8'
)
print(f'Orders loaded: {df_orders.shape}')
print(df_orders.dtypes)
print(df_orders.head(3))

Загрузка данных из базы данных

Второй источник данных — таблица клиентов в базе данных SQLite. Загружайте только столбцы, необходимые для анализа, с помощью SQL-запроса SELECT, а не всю таблицу целиком. Объедините два источника по customer_id, чтобы дополнить каждый заказ демографическими данными клиента. Перед объединением убедитесь, что ключи customer_id имеют одинаковый тип в обоих источниках: распространённая причина незаметных ошибок объединения — сравнение ключа типа int32 с ключом типа string.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///customer_db.sqlite')

df_customers = pd.read_sql_query(
    '''
    SELECT customer_id, customer_name, country,
           acquisition_channel, signup_date
    FROM customers
    ''',
    con=engine,
    dtype={'customer_id': 'int32'},
    parse_dates=['signup_date']
)
print(f'Customers loaded: {df_customers.shape}')
print(df_customers.dtypes)
print(df_customers.head(3))

Объединение двух источников

Объедините заказы с клиентами по customer_id с помощью левого объединения, чтобы сохранить все заказы, даже если запись о клиенте отсутствует. После объединения проверьте, сколько заказов не имеет соответствующего клиента (customer_name.isna().sum()) — это важный показатель качества данных, который стоит изучить. Проверьте размер получившегося DataFrame, чтобы убедиться, что объединение не привело к неожиданному дублированию или удалению строк. Зафиксируйте логику объединения в комментарии для будущих сопровождающих.

import pandas as pd

# Left join: keep all orders, enrich with customer data where available
df = pd.merge(
    df_orders,
    df_customers,
    on='customer_id',
    how='left'
)

print(f'Orders: {len(df_orders)}, Customers: {len(df_customers)}')
print(f'Merged: {df.shape}')
unmatched = df['customer_name'].isna().sum()
print(f'Orders with no matching customer: {unmatched} ({unmatched/len(df):.1%})')

Полный список проверок данных

После загрузки и объединения выполните систематическую проверку данных до начала анализа. Проверьте: общее количество строк и столбцов, пропущенные значения в каждом столбце (в процентах), типы данных всех столбцов, дублирующиеся идентификаторы заказов, охват диапазона дат, отрицательные значения в числовых столбцах и кардинальность категориальных столбцов. Зафиксируйте результаты в текстовом отчёте. Выявление проблем качества данных на этом этапе предотвращает незаметные ошибки в последующих расчётах KPI.

import pandas as pd

def audit_dataframe(df, name='DataFrame'):
    print(f'=== Audit: {name} ===')
    print(f'Shape: {df.shape}')
    print(f'Date range: {df["order_date"].min()} to {df["order_date"].max()}')
    print(f'Duplicate order_ids: {df["order_id"].duplicated().sum()}')
    print('Missing values:')
    missing = df.isnull().sum()
    print(missing[missing > 0].to_string())
    print('Negative quantities:', (df['quantity'] < 0).sum())
    print('Negative prices:', (df['unit_price'] < 0).sum())
    print()

audit_dataframe(df, 'Merged Orders + Customers')

Исправление аномалий при разборе дат

Столбцы с датами из экспортированных CSV часто содержат пограничные случаи: будущие даты, которых не должно быть, даты неправильного года (распространённая ошибка ввода) или отсутствующие даты для отменённых заказов. После разбора дат проверьте допустимый диапазон и замените значения за его пределами на NaT. Также проверьте заказы, в которых order_date < customer signup_date, — это невозможные события, указывающие на проблемы качества данных, которые следует отметить в отчёте о проверке.

import pandas as pd
from datetime import datetime

# Flag impossible dates
df['date_valid'] = (
    (df['order_date'] >= '2024-01-01') &
    (df['order_date'] <= datetime.now())
)
print('Invalid order dates:', (~df['date_valid']).sum())

# Flag orders before customer signup
df['signup_date'] = pd.to_datetime(df['signup_date'])
df['date_before_signup'] = df['order_date'] < df['signup_date']
print('Orders before customer signup:', df['date_before_signup'].sum())

# Set invalid dates to NaT
df.loc[~df['date_valid'], 'order_date'] = pd.NaT

Обработка отрицательных количеств и возвратов

Отрицательные количества в таблице заказов обычно обозначают возвраты или возмещения. Вместо простого удаления разделите их на два DataFrame: положительные заказы и возвраты. Это позволит отдельно рассчитать валовую выручку (только положительные заказы) и чистую выручку (положительные и отрицательные значения), что даст более точное представление о бизнесе. Добавьте в каждую строку логический столбец is_return и сохраните оба набора в объединённом DataFrame для целей проверки.

import pandas as pd

# Tag returns
df['is_return'] = df['quantity'] < 0

returns = df[df['is_return']]
orders = df[~df['is_return']]

print(f'Normal orders: {len(orders)}')
print(f'Returns/refunds: {len(returns)} ({len(returns)/len(df):.1%})')
print(f'Return rate by category:')
print(
    df.groupby('category')['is_return']
    .mean()
    .sort_values(ascending=False)
    .round(3)
)

Проверка полноты объединения

После левого объединения убедитесь, что оно выполнено ожидаемым образом. Подсчитайте, сколько уникальных значений customer_id встречается в заказах, но отсутствует в таблице клиентов. Это осиротевшие записи — клиенты, разместившие заказы, но не имеющие записи о клиенте. Они могут соответствовать удалённым аккаунтам, гостевым покупкам или разрыву в конвейере обработки данных. Зафиксируйте количество и решите, следует ли исключить их из анализа удержания, но включить в итоги выручки.

import pandas as pd

order_customers = set(df_orders['customer_id'].unique())
customer_ids = set(df_customers['customer_id'].unique())

orphans = order_customers - customer_ids
print(f'Customer IDs in orders not in customer table: {len(orphans)}')
print(f'Coverage: {len(order_customers & customer_ids) / len(order_customers):.1%} of order customers have records')

# Revenue from unmatched customers
orphan_revenue = df[df['customer_id'].isin(orphans)]['unit_price'].sum()
print(f'Revenue from orphan customers: ${orphan_revenue:,.0f}')

Сохранение проверенного набора данных

После проверки сохраните очищенный и объединённый набор данных в формате Parquet, чтобы последующие этапы конвейера (создание признаков, расчёт KPI, визуализация) могли мгновенно загрузить его без повторного объединения и разбора данных. Запишите отдельные файлы для очищенных заказов и DataFrame с возвратами. Такая организация контрольных точек позволяет возобновлять работу конвейера и отлаживать последующие этапы без повторного запуска загрузки.

import os
import pandas as pd

OS_DIR = 'output/'
os.makedirs(OS_DIR, exist_ok=True)

# Save clean orders (excluding returns and invalid dates)
clean_orders = df[
    (~df['is_return']) &
    df['order_date'].notna()
].copy()

clean_orders.to_parquet(OS_DIR + 'clean_orders.parquet', index=False)
df[df['is_return']].to_parquet(OS_DIR + 'returns.parquet', index=False)

print(f'Clean orders saved: {len(clean_orders):,} rows')
print(f'Returns saved: {len(df[df["is_return"]]):,} rows')
print(f'Files in {OS_DIR}: {os.listdir(OS_DIR)}')

Отчёт с итогами проверки

Заключительный этап загрузки данных — создание краткого итогового отчёта о проверке, в котором зафиксированы обнаруженные результаты. Это может быть выведенный журнал или markdown-файл. Включите: количество строк, загруженных из каждого источника, долю совпадений при объединении, диапазон дат, процент пропущенных значений, количество найденных возвратов и все аномалии. Итоговый отчёт становится частью конечного результата и помогает заинтересованным сторонам убедиться, что данные были должным образом очищены до начала анализа.

import pandas as pd
from datetime import datetime

def write_audit_summary(df, path):
    lines = [
        '# Data Ingestion Audit',
        f'Generated: {datetime.now().strftime("%Y-%m-%d %H:%M")}',
        '',
        f'- Total records after merge: {len(df):,}',
        f'- Clean orders: {(~df["is_return"]).sum():,}',
        f'- Returns: {df["is_return"].sum():,}',
        f'- Date range: {df["order_date"].min().date()} to {df["order_date"].max().date()}',
        f'- Unique customers: {df["customer_id"].nunique():,}',
        f'- Unique categories: {df["category"].nunique()}',
        f'- Missing unit_price: {df["unit_price"].isna().sum()}'
    ]
    with open(path, 'w') as f:
        f.write('\n'.join(lines))

write_audit_summary(df, 'output/audit.md')
print('Audit summary written.')

Быстрая проверка

Проверьте, насколько хорошо Вы усвоили концепции анализа данных из этого урока.

Итоги урока

В этом уроке Вы узнали, что заранее определённые цели и конфигурация помогают сделать конвейер целенаправленным и удобным для сопровождения, явно заданные аргументы dtype и parse_dates в read_csv предотвращают незаметные ошибки типов, а систематический список проверок данных (дубликаты, пропущенные значения, невозможные даты, отрицательные количества) выявляет проблемы качества до того, как они исказят расчёты KPI. Далее Вы очистите данные и создадите признаки для анализа.

Можно начать бесплатно

Изучай Python с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
30
Уроки
120

Часто задаваемые вопросы

Урок «Настройка проекта и загрузка данных» бесплатный?

Да — полный текст урока «Настройка проекта и загрузка данных» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Pandas & NumPy Academy, подпишись на CoddyKit PRO. Курс Pandas & NumPy Academy содержит 4 уроков всего.

Чему я научусь в уроке «Настройка проекта и загрузка данных»?

Определите цели проекта, загрузите данные из CSV и базы SQLite, объедините источники и выполните полный аудит объединённого набора данных Ты практикуешь Pandas & NumPy Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Pandas & NumPy Academy?

Предыдущий опыт не требуется. Pandas & NumPy Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «Настройка проекта и загрузка данных»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Pandas & NumPy Academy?

Да. Каждый урок Pandas & NumPy Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Настройка проекта и загрузка данных
  2. Очистка данных и конструирование признаков
  3. Анализ и вычисление KPI
  4. Финальная визуализация и экспорт отчёта
← Назад к Pandas & NumPy Academy