Обзор

Когда дело доходит до определения ваших лучших клиентов, лучше всего подходит старый принцип матрицы RFM. RFM расшифровывается как "Время с недавнего времени", "Частота" и "Деньги". Это метод сегментации клиентов, который использует прошлое покупательское поведение для разделения клиентов на группы.

Расчет рейтинга RFM

НЕДАВНИЕ (R): количество дней с момента последней покупки
ЧАСТОТА (F): Общее количество покупок
ДЕНЕЖНАЯ СТОИМОСТЬ (M): Общая сумма денег, потраченных этим клиентом

Шаг 1. Рассчитайте показатели RFM для каждого клиента.

Шаг 2: Добавьте номера сегментов в таблицу RFM.

Шаг 3. Отсортируйте в соответствии с оценками RFM лучших клиентов (111 баллов).

Поскольку RFM основан на данных об активности пользователей, первое, что нам нужно, это данные.

Данные

Набор данных, который мы будем использовать, тот же, что и при Анализе рыночной корзины - Набор данных розничной онлайн-торговли, который можно загрузить из Репозитория машинного обучения UCI.

import pandas as pd
import warnings
warnings.filterwarnings('ignore')
df = pd.read_excel("Online_Retail.xlsx")
df.head()
df1 = df

Набор данных содержит все транзакции, произошедшие с 01/12/2010 по 09/12/2011 для зарегистрированного онлайн-продавца из Великобритании.

Загрузка данных заняла несколько минут, поэтому я сохранил копию в качестве резервной.

Изучите данные - проверка и новые переменные

  1. Отсутствуют значения в важных столбцах;
  2. Распределение клиентов в каждой стране;
  3. Цена за единицу и количество должны ›0;
  4. Дата выставления счета должна ‹сегодня.
df1.Country.nunique()

38

Всего было 38 уникальных стран:

df1.Country.unique()

array (['Соединенное Королевство', 'Франция', 'Австралия', 'Нидерланды', 'Германия',
'Норвегия', 'EIRE', 'Швейцария', 'Испания', "Польша", "Португалия",
"Италия", "Бельгия", "Литва", "Япония", "Исландия",
"Нормандские острова", "Дания", "Кипр", " Швеция, Австрия,
Израиль, Финляндия, Бахрейн, Греция, Гонконг, Сингапур,
Ливан, Объединенные Арабские Эмираты, "Саудовская Аравия", "Чешская Республика",
"Канада", "Не указано", "Бразилия", "США", "Европейское сообщество",
"Мальта", "RSA"], dtype = объект

customer_country=df1[['Country','CustomerID']].drop_duplicates()
customer_country.groupby(['Country'])['CustomerID'].aggregate('count').reset_index().sort_values('CustomerID', ascending=False)

Более 90% клиентов в данных из Соединенного Королевства. Некоторые исследования показывают, что кластеры клиентов различаются в зависимости от географического положения, поэтому здесь я ограничусь данными только по Соединенному Королевству.

df1 = df1.loc[df1['Country'] == 'United Kingdom']

Проверьте, есть ли пропущенные значения в каждом столбце.

В столбце CustomerID 133600 пропущенных значений, и, поскольку наш анализ основан на клиентах, мы удалим эти пропущенные значения.

df1 = df1[pd.notnull(df1['CustomerID'])]

Проверьте минимальные значения в столбцах UnitPrice и Quantity.

df1 = df1[pd.notnull(df1['CustomerID'])]

0.0

df1.Quantity.min()

-80995

Удалите отрицательные значения в столбце "Количество".

df1 = df1[(df1['Quantity']>0)]
df1.shape
df1.info()

(354345, 8)

После очистки данных мы имеем дело с 354 345 строками и 8 столбцами.

Проверьте уникальное значение для каждого столбца.

def unique_counts(df1):
   for i in df1.columns:
       count = df1[i].nunique()
       print(i, ": ", count)
unique_counts(df1)

InvoiceNo: 16649
StockCode: 3645
Описание: 3844
Количество: 294
InvoiceDate: 15615
UnitPrice: 403
CustomerID: 3921
Страна: 1

Добавьте столбец для общей цены.

df1['TotalPrice'] = df1['Quantity'] * df1['UnitPrice']

Узнайте дату первого и последнего заказа в данных.

df1['InvoiceDate'].min()

Отметка времени («2010–12–01 08:26:00»)

df1['InvoiceDate'].max()

Отметка времени («2011–12–09 12:49:00»)

Поскольку новизна рассчитывается для определенного момента времени, а дата последнего счета - 2011–12–09, мы будем использовать 2011–12–10 для расчета давности.

import datetime as dt
NOW = dt.datetime(2011,12,10)
df1['InvoiceDate'] = pd.to_datetime(df1['InvoiceDate'])

RFM сегментация клиентов

Отсюда начинается RFM-сегментация.

Создайте таблицу RFM

rfmTable = df1.groupby('CustomerID').agg({'InvoiceDate': lambda x: (NOW - x.max()).days, 'InvoiceNo': lambda x: len(x), 'TotalPrice': lambda x: x.sum()})
rfmTable['InvoiceDate'] = rfmTable['InvoiceDate'].astype(int)
rfmTable.rename(columns={'InvoiceDate': 'recency', 
                         'InvoiceNo': 'frequency', 
                         'TotalPrice': 'monetary_value'}, inplace=True)

Рассчитайте показатели RFM для каждого клиента

Интерпретация:

  • CustomerID 12346 имеет частоту: 1, денежное выражение: 77 183,60 долларов США и новизну: 325 дней.
  • CustomerID 12747 имеет частоту: 103, денежное выражение: 4 196,01 доллара США и новизну: 2 дня.

Давайте проверим данные первого покупателя.

Первый покупатель совершил покупку только один раз, купил один товар в большом количестве (74 215). Цена за единицу очень низкая; возможно распродажа.

Разделите показатели

Самый простой способ разбить показатели на сегменты - использовать квартили.

  1. Это дает нам отправную точку для подробного анализа.
  2. 4 сегмента легко понять и объяснить.
quantiles = rfmTable.quantile(q=[0.25,0.5,0.75])
quantiles = quantiles.to_dict()

Создайте сегментированную таблицу RFM

segmented_rfm = rfmTable

Самая низкая давность, самая высокая частота и денежные суммы - наши лучшие клиенты.

def RScore(x,p,d):
    if x <= d[p][0.25]:
        return 1
    elif x <= d[p][0.50]:
        return 2
    elif x <= d[p][0.75]: 
        return 3
    else:
        return 4
    
def FMScore(x,p,d):
    if x <= d[p][0.25]:
        return 4
    elif x <= d[p][0.50]:
        return 3
    elif x <= d[p][0.75]: 
        return 2
    else:
        return 1

Добавьте номера сегментов во вновь созданную сегментированную таблицу RFM

segmented_rfm['r_quartile'] = segmented_rfm['recency'].apply(RScore, args=('recency',quantiles,))
segmented_rfm['f_quartile'] = segmented_rfm['frequency'].apply(FMScore, args=('frequency',quantiles,))
segmented_rfm['m_quartile'] = segmented_rfm['monetary_value'].apply(FMScore, args=('monetary_value',quantiles,))
segmented_rfm.head()

Сегменты RFM разбивают клиентскую базу на воображаемый трехмерный куб, который трудно визуализировать. Однако мы можем разобраться.

Добавьте новый столбец, чтобы объединить оценку RFM: 111 - это наивысшая оценка, как мы определили ранее.

segmented_rfm['RFMScore'] = segmented_rfm.r_quartile.map(str) 
                            + segmented_rfm.f_quartile.map(str) 
                            + segmented_rfm.m_quartile.map(str)
segmented_rfm.head()

Очевидно, что первый покупатель - это вовсе не наш лучший покупатель.

Кто входит в десятку наших лучших клиентов?

segmented_rfm[segmented_rfm['RFMScore']=='111'].sort_values('monetary_value', ascending=False).head(10)

Учить больше

Интересно узнать больше?

  1. Kimberly Coffey имеет отличный учебник по тому же набору данных с использованием R.
  2. Пакет R Дэниела Маккарти и Эдварда Уодсворта - Buy’ Til You Die - A Walkthrough .
  3. Сегментация клиентов продавца вина из блога yhat.

Исходный код, создавший этот пост, можно найти здесь. Я был бы рад получить отзывы или вопросы по любому из вышеперечисленного.

ссылка: Blast Analytics and Marketing