Pandas отчет о продажах
В качестве источника данных используется — https://www.kaggle.com/carrie1/ecommerce-data.
Для начала подключается Pandas и вычитывается файл:
import pandas as pd df = pd.read_csv('ecommerce-data.zip',encoding = "cp1252") df.head()
Теперь нужно найти пустые данные в датасете:
df.isna().mean()
Обратите внимание, что есть пустые значения в CustomerID. К сожалению метод groupby игнорирует NaN, поэтому давайте заполним его отрицательными значениями, чтобы сохранить числовой тип данных:
df['CustomerID'].fillna(-999,inplace=True)
И сразу конвертируем дату в дату питона (если pandas будет выдавать ошибки, вот здесь еще есть способы конвертации даты):
df['InvoiceDate'] = pd.to_datetime(df['InvoiceDate'],format='%m/%d/%Y %H:%M')
Давайте посмотрим какой минимальный и максимальный период представлен в датасете:
df['InvoiceDate'].min()
Timestamp (‘2010–12–01 08:26:00’)
df['InvoiceDate'].max()
Timestamp (‘2011–12–09 12:50:00’)
В датасете представлен примерно 1 год. Теперь давайте подготовим месячный отчет о продажах
1. Создание таблицы с уникальными пользователями
В реальности у нас всегда есть таблица с пользователями в базе данных, но в текущем датасете ее нет. Поэтому добавим ее. В качестве даты регистрации пользователя будем использовать минимальную дату заказа этого пользователя.
user = df.groupby(['CustomerID'])['InvoiceDate'].min().reset_index() user.head()
Переименуем колонки:
user.columns = ['CustomerID','reg_date']
Отдельно добавим месяц регистрации:
user['reg_month'] = user['reg_date'].values.astype('datetime64[M]')
Результат:
user
2. Создадим шаблонную таблицу с каждым возможным месяцем для каждого пользователя:
min_month = df['InvoiceDate'].values.astype('datetime64[M]').min() max_month = df['InvoiceDate'].values.astype('datetime64[M]').max() dr = pd.DataFrame(pd.date_range(min_month,max_month,freq='MS')) dr.columns = ['month']
Сделаем перекрестное соединение с таблицей пользователей и получить
len(user)*len(dr)
строк. В pandas это можно сделать следующим образом:
dr['key'] = 1 user['key'] = 1 report = dr.merge(user,on='key') report.head()
Проверим сколько строк получилось в новом датасете:
len(report)
Как и ожидалось 56849.
Но есть несколько лишних строк: некоторые пользователи пришли намного позже минимальной даты (2010-12), и глупо иметь записи для пользователя до того, как он пришел к нам).
report = report[report['month']>=report['reg_month']]
Давайте посмотрим на конкретного пользователя, просто чтобы проверить правильность.
report[report['CustomerID'] == 12346.0]
и еще:
report[report['CustomerID'] == 12448.0]
Теперь можно объеденить данные о продажах с датасетом пользователей. Прежде чем сделать это, нужно провести некоторую подготовку.
3. Предварительная агрегация данных.
Произведем расчет по общему объему продаж за каждый месяц для каждого клиента.
df['month'] = df['InvoiceDate'].values.astype('datetime64[M]') df['revenue'] = df['UnitPrice'] * df['Quantity'] sales_month = df.groupby(['CustomerID','month'])[['revenue']].agg('sum').reset_index() sales_month.head()
При создании новых таблиц всегда нужно следить за тем, чтобы итоговые суммы совпадали!
df['revenue'].sum()
9747747.933999998
sales_month['revenue'].sum()
9747747.934000025
4. Объеденение
Очень важно использовать LEFT JOIN! С помощью LEFT JOIN будут сохранены все строки — таким образом можно увидеть когда клиенты были активны, а когда нет:
report = report.merge(sales_month,how='left',on=['CustomerID','month']) report.head()
Проверить итоговые показатели:
df['revenue'].sum()
9747747.933999998
report['revenue'].sum()
9747747.934000023
Отлично! Теперь еще одна проверка по клиенту:
report[report['CustomerID'] == 12347.0]
Видно, что активность этого клиента не является регулярной. К примеру после 2011-01-01 наблюдается пауза в покупках в течение двух месяцев. Затем закупки начинаются снова.
5. Базовые метрики
Добавить общее количество активных и новых пользователей:
report['user'] = 1 report['new'] = (report['reg_month'] == report['month']) * 1 report['active'] = (report['revenue'] > 0) * 1 report.head()
Теперь можно создать ежемесячный отчет на основе этой таблицы:
report.groupby('month')[['revenue','user','new','active']].agg('sum')
Это очень надежный способ создания всех видов отчетов: ежедневных, еженедельных, ежемесячных.
Сразу стоит оговориться, что подобные отчеты удобнее делать через SQL, он намного мощнее. Но, если у вас нет знаний SQL и вам никто не дает доступы к базе данных, а просто делает выгрузки — PANDAS один из луших инструментов для быстрого анализа. В примере отчет делается в Jupiter