images
15/10/2020 06:55 am

Gấu Mèo đi làm Data Scientist - Phần 11: Marketing - Part 3 - RFM Segmentation

Hôm trước đọc quyển “Database Marketing”, Gấu Mèo có thấy nhắc tới việc dùng RFM để tối ưu việc click email quảng cáo. Thấy khá make sense, trưa đấy nó rủ giám đốc Marketing đi ăn để xem áp dụng luôn cho công ty.

Cả hai say sưa ngồi bàn bạc tới tận chiều, lúc đi ra mấy bạn nhân viên cứ lườm lườm… 


Phân tích hành vi khách hàng có nhiều model với việc implement rất công phu, nhưng nếu bạn đang cần một model đơn giản, có thể triển khai nhanh và quan trọng nhất là actionable thì bạn có thể dùng RFM. Cụ thể hơn nhá:


RFM bao gồm 3 yếu tố:


- Recency: khoảng thời gian giữa lần gần nhất mà khách hàng mua hàng với hiện tại


- Frequency: mức độ thường xuyên mua hàng của khách hàng


- Monetary Value: tổng giá trị mà khách hàng đã chi trả


Việc triển khai bao gồm các bước:


Bước 1: Tính các giá trị R, F, M đối với từng khách hàng


Bước 2: Đối với từng bộ giá trị R, F, M chia thành 5 lớp


R1 -> R5: Nhóm giao dịch gần gần nhất -> xa nhất

F1 -> F5: Nhóm giao dịch thường xuyên nhất -> ít giao dịch nhất

M1 -> M5: Nhóm có tổng giá trị giao dịch lớn nhất -> nhỏ nhất nhất


Bước 3: Phân loại khách hàng dựa trên việc tổng hợp kết quả bước 2


Bước 4: Thực hiện quy trình chăm sóc theo loại khách hàng


Dưới đây là các segment được phân loại:


Segment

Activity

Actionable Tip

Champion

Đã mua gần đây, đặt hàng thường xuyên và chi tiêu nhiều nhất.


Reward họ. Có thể là người sớm chấp nhận sản phẩm mới. Nhiều khả năng sẽ trở thành một kênh giới thiệu rất tốt

Loyal

Đặt hàng thường xuyên. Có tương tác các chương trình khuyến mãi.

Upsell. Đưa ra các chính sách được cá nhân hóa. Xin ý kiến reviews.

Potential Loyalist

Đã mua gần đây, chi tiêu tốt.

Cung cấp chương trình thành viên / khách hàng thân thiết. Giữ họ tham gia. Đưa ra các chính sách được cá nhân hóa.

New Customers

Khách hàng mới

Cho vào các chiến dịch onboard, bắt đầu xây dựng mối quan hệ.

Promising

Từng là khách trung thành. Chi tiêu thường xuyên và khá nhiều tiền. Nhưng lần mua cuối cùng đã cách đây vài tuần.

Cung cấp phiếu giảm giá. Đưa họ trở lại nền tảng và giữ họ tương tác. Đưa ra các đề xuất được cá nhân hóa.

Core

Khách phổ biến, mua hàng cách đây không lâu.

Đề xuất khuyến mãi có thời hạn.

Needs attention

Khách hàng cốt lõi có lần mua gần đây nhất đã xảy ra hơn một tháng trước.

Đề xuất khuyến mãi có thời hạn.. Đưa ra các chính sách được cá nhân hóa.

Can’t lose them but losing

Thực hiện các đơn đặt hàng lớn nhất và thường xuyên. Nhưng đã lâu không trở lại.

Giành lại họ thông qua gia hạn hoặc các sản phẩm mới hơn, đừng để mất họ trước đối thủ. Nói chuyện với họ nếu cần thiết. Dành thời gian để cá nhân hóa cao nhất có thể.

At Risk

Giống như “Can’t lose them but losing” nhưng lượng tiền và tần suất thấp hơn 

Gửi email được cá nhân hóa.

Đưa ra chính sách khuyến mãi

Losing but engaged

Đã thực hiện lần mua hàng cuối cùng của họ cách đây khá lâu nhưng trong 4 tuần qua, họ đã truy cập trang web hoặc mở email.

Cá nhân hóa tiêu đề của email . Thu hút sự quan tâm của họ bằng cách giảm giá cụ thể cho một sản phẩm cụ thể.

Lost

Đã thực hiện lần mua hàng gần đây nhất cách đây khá lâu và hoàn toàn không tương tác trong 4 tuần qua.

Bỏ qua trong các chiến dịch tiếp cận. 


Nhưng mà làm sao từ 3 giá trị RFM mà có thể phân thành các segment như vậy? May quá có bảng map lại luôn:


Segment

Scores

Champions

555, 554, 544, 545, 454, 455, 445

Loyal

543, 444, 435, 355, 354, 345, 344, 335

Potential Loyalist

553, 551, 552, 541, 542, 533, 532, 531, 452, 451, 442, 441, 431, 453, 433, 432, 423, 353, 352, 351, 342, 341, 333, 323

Promising

525, 524, 523, 522, 521, 515, 514, 513, 425,424, 413,414,415, 315, 314, 313

New Customers

512, 511, 422, 421 412, 411, 311

Need Attention

535, 534, 443, 434, 343, 334, 325, 324

About To Sleep

331, 321, 312, 221, 213, 231, 241, 251

At Risk

255, 254, 245, 244, 253, 252, 243, 242, 235, 234, 225, 224, 153, 152, 145, 143, 142, 135, 134, 133, 125, 124

Cannot Lose Them

155, 154, 144, 214,215,115, 114, 113

Hibernating customers

332, 322, 231, 241, 251, 233, 232, 223, 222, 132, 123, 122, 212, 211

Lost customers

111, 112, 121, 131,141,151


“Nếu bạn thắc mắc mấy số 543,..là gì thì đấy là nhóm RFM tương ứng. Ví dụ 312 thì R thuộc nhóm 3, F thuộc nhóm 1, M thuộc 2”


Lý thuyết là thế, nhưng khi làm sẽ có một số chỗ làm cho bạn đau đầu.


Như việc chia nhóm: bạn có thể dùng quantile, dùng ML để cluster, cũng có thể bạn đơn giản chỉ chia đều số lượng người

Cả phần tính frequency bạn cũng phải chọn ra period phù hợp với biz của công ty mình.


Để hình dung qua thì gấu Mèo cũng chuẩn bị sẵn một đoạn code:


Các bạn có thể lấy data ở:

https://archive.ics.uci.edu/ml/datasets/Online+Retail

Đầu tiên chúng ta sẽ import các thư viện cần thiết và load dữ liệu 

import pandas as pd

from datetime import timedelta

import matplotlib.pyplot as plt

sales = pd.read_excel('Online Retail.xlsx')

Dữ liệu này có nhiều data lỗi nên chúng ta sẽ clean đi 

sales.dropna(subset=['CustomerID'], inplace=True)

sales = sales[(sales['Quantity'] >= 0)]

sales = sales[sales['UnitPrice'] >= 0]

Tính giá mua hàng cả đơn:

sales['Price'] = sales['Quantity'] * sales['UnitPrice']

Nhóm lại theo từng khách hàng

orders = sales.groupby(['InvoiceNo', 'InvoiceDate', 'CustomerID']).agg({'Price': lambda x: x.sum()}).reset_index()

Tính toán RFM

NOW = orders['InvoiceDate'].max() + timedelta(days=1)

period = 365

orders['DaysSinceOrder'] = orders['InvoiceDate'].apply(lambda x: (NOW - x).days)

aggr = {

    'DaysSinceOrder': lambda x: x.min(),  # the number of days since last order (Recency)

    'InvoiceDate': lambda x: len([d for d in x if d >= NOW - timedelta(days=period)]), # the total number of orders in the last period (Frequency)

}

rfm = orders.groupby('CustomerID').agg(aggr).reset_index()

rfm.rename(columns={'DaysSinceOrder': 'Recency', 'InvoiceDate': 'Frequency'}, inplace=True)

rfm['Monetary'] = 

rfm['CustomerID'].apply(lambda x: orders[(orders['CustomerID'] == x) & \

 (orders['InvoiceDate'] >=NOW-timedelta(days=period))]['Price'].sum())

Tính toán RFM score

quintiles = rfm[['Recency', 'Frequency', 'Monetary']].quantile([.2, .4, .6, .8]).to_dict()

def r_score(x):

    if x <= quintiles['Recency'][.2]:

        return 5

    elif x <= quintiles['Recency'][.4]:

        return 4

    elif x <= quintiles['Recency'][.6]:

        return 3

    elif x <= quintiles['Recency'][.8]:

        return 2

    else:

        return 1    

def fm_score(x, c):

    if x <= quintiles[c][.2]:

        return 1

    elif x <= quintiles[c][.4]:

        return 2

    elif x <= quintiles[c][.6]:

        return 3

    elif x <= quintiles[c][.8]:

        return 4

    else:

        return 5    

rfm['R'] = rfm['Recency'].apply(lambda x: r_score(x))

rfm['F'] = rfm['Frequency'].apply(lambda x: fm_score(x, 'Frequency'))

rfm['M'] = rfm['Monetary'].apply(lambda x: fm_score(x, 'Monetary'))

rfm['RFM Score'] = rfm['R'].map(str) + rfm['F'].map(str) + rfm['M'].map(str)

Và chúng ta thu được kết quả như hình

Bây h chúng ta sẽ map lại theo bảng phía trên để ra được segment của khách hàng:

def segment_map(rfm_str):

    rfm = int(rfm_str)

    if rfm in (555, 554, 544, 545, 454, 455, 445):

        return 'Champions'

    if rfm in (543, 444, 435, 355, 354, 345, 344, 335):

        return 'Loyal'

    if rfm in (553, 551, 552, 541, 542, 533, 532, 531, 452, 451, 442, 441, 431, 453, 433, 432, 423, 353, 352, 351, 342, 341, 333, 323):

        return 'Potential Loyalist'

    if rfm in (525, 524, 523, 522, 521, 515, 514, 513, 425,424, 413,414,415, 315, 314, 313):

        return 'Promising'

    if rfm in (512, 511, 422, 421, 412, 411, 311):

        return 'New Customers'

    if rfm in (535, 534, 443, 434, 343, 334, 325, 324):

        return 'Need Attention'

    if rfm in (331, 321, 312, 221, 213, 231, 241, 251):

        return 'About To Sleep'

    if rfm in (255, 254, 245, 244, 253, 252, 243, 242, 235, 234, 225, 224, 153, 152, 145, 143, 142, 135, 134, 133, 125, 124):

        return 'At Risk'

    if rfm in (155, 154, 144, 214,215,115, 114, 113):

        return 'Cannot Lose Them'

    if rfm in (332, 322, 231, 241, 251, 233, 232, 223, 222, 132, 123, 122, 212, 211):

        return 'Hibernating customers'

    if rfm in (111, 112, 121, 131,141,151):

        return 'Lost customers'


rfm['Segment'] = rfm['RFM Score'].map(segment_map)

rfm.head()


Yeah, như vậy là khi có một ID khách hàng chúng ta có thể biết được họ thuộc nhóm nào và cần có chính sách ra sao rồi. Chúng ta cũng có thể lấy ra danh sách theo từng nhóm để chăm sóc.

Nghe đơn giản nhỉ. Nhưng thực tế là mỗi biz mỗi khác nên khi làm trên thực tế Gấu Mèo có customize việc chia nhóm. Ngoài ra việc chăm sóc cũng phải phụ thuộc số lượng trên từng nhóm và budget của công ty nữa

Đoạn code trên Gấu Mèo không có tối ưu gì hết, cũng không chuyển nó thành API, các bạn dev nếu tham khảo thì chú ý nhé.

Bài dài quá rồi, Gấu Mèo xin gác bút đi ngủ.

Mời các bạn đọc thêm bài Gấu mèo đi làm Data Scientist - Phần 11: Marketing - Part 2: Xây dựng hệ thống tracking cho marketing.

và bài tiếp theo: Gấu Mèo đi làm Data Scientist - Phần 12: Customer Churn Prediction: Never let me go - Part 1

- Tech Zone -

Thư giãn chút nào!!!

Bài viết liên quan