RFM анализ в Python

В моём телеграм канале я запустил новую рубрику — task. Суть рубрики — Я публикую задание каждый вторник с постановкой задачи и ссылкой на данные. Код с описанием хода решения задачи я размещаю в четверг. Задачи сделаны так, что бы на их решение нужно потратить не более пары часов. Подробный пост — https://t.me/renat_alimbekov/71

Постановка задачи

Первая задача — сделать RFM-анализ. Он делит пользователей на сегменты в зависимости от давности (Recency), частоты (Frequency) и общей суммы платежей (Monetary).

  • Recency — разница между текущей датой и датой последнего платежа
  • Frequency — количество транзакций
  • Monetary — сумма покупок

Эти три показателя нужно рассчитать отдельно для каждого покупателя. После чего поставить оценки от 1-3 или 1-5. Чем шире диапазон, тем более узкие сегменты у нас получатся.

Баллы можно выставить с использованием квантилей. Сортируем данные по одному из критериев и делим на равныегруппы.

Для этой задачи используем публичный датасет: https://www.kaggle.com/olistbr/brazilian-ecommerce и файлы olist_orders_dataset.csv и olist_order_payments_dataset.csv. Соединить их можно по order_id.

Реализация RFM на Python

import numpy as np
import pandas as pd
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
from datetime import date,timedelta
df_orders = pd.read_csv('data/olist_orders_dataset.csv')
df_payments = pd.read_csv('data/olist_order_payments_dataset.csv')

Импортируем все необходимые библиотеки и считаем файлы.

Мы будем опираться на дату доставки заказа первозчиком (order_delivered_carrier_date), поэтому преобразуем её в datetime64. Создадим индекс order_id и соединим наши датасеты по нему.

df_orders['order_delivered_carrier_date'] = pd.to_datetime(df_orders['order_delivered_carrier_date'])
df_payments = df_payments.set_index('order_id')
df_orders = df_orders.set_index('order_id')
order_payment = df_orders.join(df_payments)

Так как датасет не самый свежий, вместо текущей даты будем использовать max+1. Для создания recency, frequency и monetary мы сгруппируем наши записи по customer_id.

last_date = order_payment['order_delivered_carrier_date'].max() + timedelta(days=1)
rfmTable = order_payment.reset_index().groupby('customer_id').agg({'order_delivered_carrier_date': lambda x: (last_date - x.max()).days,
                                                 'order_id': lambda x: len(x), 
                                                 'payment_value': lambda x: x.sum()})
rfmTable.rename(columns={'order_delivered_carrier_date': 'recency', 
                          'order_id': 'frequency', 
                          'payment_value': 'monetary_value'}, inplace=True)
RFM анализ
RFM анализ

Теперь нам нужно выставить оценки. Мы будем разбивать на диапазон от 1 до 5. Чем шире диапазон, тем более точные наши группы, но в тоже время работать с большим количествов комбинаций сложнее.

quantiles = rfmTable.quantile(q=[0.20, 0.40, 0.60, 0.80])
quantiles = quantiles.to_dict()
segmented_rfm = rfmTable

def RScore(x,p,d):
     if x <= d[p][0.20]:
         return 1
     elif x <= d[p][0.40]:
         return 2
     elif x <= d[p][0.60]: 
         return 3
     elif x<=d[p][0.80]:
         return 4
     else:
         return 5

segmented_rfm['r_quartile'] = segmented_rfm['recency'].apply(RScore, args=('recency',quantiles,))
segmented_rfm['f_quartile'] = segmented_rfm['frequency'].apply(RScore, args=('frequency',quantiles,))
segmented_rfm['m_quartile'] = segmented_rfm['monetary_value'].apply(RScore, args=('monetary_value',quantiles,))
segmented_rfm['RFMScore'] = segmented_rfm.r_quartile.map(str) + segmented_rfm.f_quartile.map(str) + segmented_rfm.m_quartile.map(str)
print(segmented_rfm.head())
RFM Score

Отдельно можем посмотреть среднее значение recency по всем RFMScore.

fig=plt.figure(figsize=(18, 16), dpi= 80, facecolor='w', edgecolor='k')
 segmented_rfm.groupby('RFMScore').agg('recency').mean().plot(kind='bar', colormap='Blues_r')
plt.show()
Recency Score

Пока возможно это не очень информативно. Давайте попробуем понять как использовать результаты анализа.

Как использовать результаты RFM анализа

Цель RFM анализа сформировать сегменты и в зависимости от сегмента воздействовать на них определенным образом. Например: предложить бонус, льготу, отправить push или email уведомление. Важно делать это таргетировано.

Эффект от использования RFM анализа может быть следующим: удержание клиентов, повышение дохода, повышение лояльность клиентов.

Примеры интерпретации сегментов RFM анализа:

  • R=5, F=5, M=5 — платят чаcто, много и недавно. Самые лояльным и активные пользователи.
  • R=1, F=1, M=1 — платят мало, редко и давно. Скорее всего потерянные клиенты. Возможно не стоит предпринять действия по их возврату, если цена привлечения выше ожидаемой прибыли.
  • R=1/2, F=4/5, M=4/5 — лояльные пользователи на грани ухода. Предлагаем им бонус, скидку и пытаемся их вернуть.
  • R=4/5, F=1, M=1/2/3/4/5 — пользователи недавно совершили платеж. Пробуем их стимулировать покупать еще.

Заключение

Разобрали простой и эффективный способ сегментации пользователей/ клиентов. RFM анализ поможет вам выбрать таргетированное воздействие и таким образом повысить доход, или удержать пользователей.

Мой курс анализ медицинских изображений в Python

Share it

Если вам понравилась заметка - подписывайтесь на мой канал в телеграме https://t.me/renat_alimbekov или вы можете поддержать меня Become a Patron!


Интересные записи в этой рубрике: