, September 29, 2022

0 kết quả được tìm thấy

Data Driven Growth (P.2): Phân khúc khách hàng theo RFM

  • Đăng bởi  Pum
  •  Jun 14, 2022

  •   11 min reads
Data Driven Growth (P.2): Phân khúc khách hàng theo RFM

Trong bài viết trước, chúng ta đã phân tích các chỉ số chính trong các hoạt động kinh doanh bán lẻ trực tuyến. Trong bài viết này, chúng ta sẽ tập trung vào khách hàng và sự phân khúc khách hàng.

Đến lúc này sẽ có nhiều bạn đặt ra câu hỏi, tại sao chúng ta cần phải thực hiện giai đoạn này?  

Vì mỗi khách hàng cần có sự đối xử khác nhau tùy vào tính cách, hành vi và độ tuổi của họ, không thể cùng đối xử với mọi khách hàng theo cùng một cách giống nhau.

Như cùng một nội dung, một kênh và cùng một tầm quan trọng được. Vì như vậy khách hàng họ sẽ tìm đến một thương hiệu khác hiểu và tôn trọng họ hơn.

Bạn có thể thực hiện nhiều phân đoạn khác nhau tùy theo nhu cầu mà bạn đang tìm hiểu. Chẳng hạn như, bạn muốn tăng tỷ lệ giữ chân khách hàng, bạn có thể thực hiện phân đoạn dựa trên xác suất churn. Và bạn còn chần chừ gì nữa mà không bắt tay vào việc hành động ngay!

Ngoài ra cũng có những phương pháp phân đoạn rất phổ biến và hữu ích khác. Dưới đây chúng ta sẽ tìm hiểu một trong số chúng là: RFM

Bạn có thể tham khảo thêm bài viết này để biết rõ hơn về khái niệm RFM là gì nhé!

Phân loại khách hàng theo RFM - RFM Segmentation
Vì sao phải cần phân loại khách hàng? Bởi vì bạn không thể đối xử với họ giống như nhau, sử dụng cùng một loại nội dung, cùng một kênh truyền thông và cùng độ ưu tiên
Phân loại khách hàng theo RFM - RFM Segmentation

Về phương pháp luận, chúng ta cần tính toán lần truy cập gần đây, tần suất, giá trị tiền tệ cũng như áp dụng machine learning không giám sát để xác định các nhóm (cụm) khác nhau. Hãy bắt đầu viết mã và xem cách thực hiện phân cụm RFM dưới đây nhé!

Lần truy cập gần đây

Để tính toán lần truy cập gần đây, chúng ta cần tìm hiểu  xem ngày mua hàng gần đây nhất của từng khách hàng và xem xem họ đã không hoạt động trong bao nhiêu ngày.

Sau đó chúng ta sẽ áp dụng công thức sau: K-means * clustering để kiếm ra số lần truy cập gần đây của khách hàng.

Trước khi chuyển sang tính toán lần truy cập gần đây, hãy cùng tóm tắt lại công việc dữ liệu mà chúng ta đã thực hiện trước đây.

# import libraries
from datetime import datetime, timedelta
import pandas as pd
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from __future__ import division

import plotly.plotly as py
import plotly.offline as pyoff
import plotly.graph_objs as go

#inititate Plotly
pyoff.init_notebook_mode()

#load our data from CSV
tx_data = pd.read_csv('data.csv')

#convert the string date field to datetime
tx_data['InvoiceDate'] = pd.to_datetime(tx_data['InvoiceDate'])

#we will be using only UK data
tx_uk = tx_data.query("Country=='United Kingdom'").reset_index(drop=True)

Bây giờ chúng ta có thể tính toán lần truy cập gần đây:

#create a generic user dataframe to keep CustomerID and new segmentation scores
tx_user = pd.DataFrame(tx_data['CustomerID'].unique())
tx_user.columns = ['CustomerID']

#get the max purchase date for each customer and create a dataframe with it
tx_max_purchase = tx_uk.groupby('CustomerID').InvoiceDate.max().reset_index()
tx_max_purchase.columns = ['CustomerID','MaxPurchaseDate']

#we take our observation point as the max invoice date in our dataset
tx_max_purchase['Recency'] = (tx_max_purchase['MaxPurchaseDate'].max() - tx_max_purchase['MaxPurchaseDate']).dt.days

#merge this dataframe to our new user dataframe
tx_user = pd.merge(tx_user, tx_max_purchase[['CustomerID','Recency']], on='CustomerID')

tx_user.head()

#plot a recency histogram

plot_data = [
    go.Histogram(
        x=tx_user['Recency']
    )
]

plot_layout = go.Layout(
        title='Recency'
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Khung dữ liệu mới tx_user của chúng ta hiện chứa dữ liệu lần truy cập gần đây:

Để có một cái nhìn nhanh về lần gần đây trông như thế nào, chúng ta có thể sử dụng phương thức .describe () của pandas. Nó sẽ hiển thị giá trị trung bình, tối thiểu, tối đa, số lượng và phần trăm dữ liệu.

Đoạn mã ở trên có biểu đồ để cho chúng ta thấy sự phân bổ lần truy cập gần đây của các khách hàng.

Tiếp theo, chúng ta sẽ đến với một phần khá là thú vị.

Chúng ta sẽ áp dụng phân cụm K-mean để chỉ định điểm số lần truy cập gần đây. Nhưng chúng ta cần biết có bao nhiêu cụm đối với thuật toán K-mean. Để tìm ra nó, chúng ta sẽ áp dụng phương pháp Elbow.

Phương pháp Elbow chỉ đơn giản cho biết số cụm tối ưu để có quán tính tối ưu. Đoạn mã và biểu đồ quán tính như sau:

from sklearn.cluster import KMeans

sse={}
tx_recency = tx_user[['Recency']]
for k in range(1, 10):
    kmeans = KMeans(n_clusters=k, max_iter=1000).fit(tx_recency)
    tx_recency["clusters"] = kmeans.labels_
    sse[k] = kmeans.inertia_ 
plt.figure()
plt.plot(list(sse.keys()), list(sse.values()))
plt.xlabel("Number of cluster")
plt.show()
Đồ thị quán tính

Ở đây có vẻ như số 3 là cái tối ưu. Dựa theo yêu cầu kinh doanh, chúng ta có thể tiếp tục với ít hoặc nhiều cụm hơn. Chúng ta sẽ chọn  số4 cho ví dụ này:

#build 4 clusters for recency and add it to dataframe
kmeans = KMeans(n_clusters=4)
kmeans.fit(tx_user[['Recency']])
tx_user['RecencyCluster'] = kmeans.predict(tx_user[['Recency']])

#function for ordering cluster numbers
def order_cluster(cluster_field_name, target_field_name,df,ascending):
    new_cluster_field_name = 'new_' + cluster_field_name
    df_new = df.groupby(cluster_field_name)[target_field_name].mean().reset_index()
    df_new = df_new.sort_values(by=target_field_name,ascending=ascending).reset_index(drop=True)
    df_new['index'] = df_new.index
    df_final = pd.merge(df,df_new[[cluster_field_name,'index']], on=cluster_field_name)
    df_final = df_final.drop([cluster_field_name],axis=1)
    df_final = df_final.rename(columns={"index":cluster_field_name})
    return df_final

tx_user = order_cluster('RecencyCluster', 'Recency',tx_user,False)

Chúng ta đã tính toán các cụm và gán chúng cho từng khách hàng trong dataframe tx_user.

Chúng ta có thể thấy các cụm với lần truy cập gần đây có các đặc điểm khác nhau như thế nào. Khách hàng ở cụm 1 rất gần so với cụm 2.

Chúng ta đã thêm một hàm vào mã, đó là order_cluster (). K-mean chỉ định các cụm dưới dạng số nhưng không theo cách có thứ tự. Chúng ta không thể nói cụm 0 là kém nhất và cụm 4 là tốt nhất.

Phương thức order_cluster () thực hiện điều này và khung dữ liệu mới của chúng ta đã trông gọn gàng hơn rất nhiều:

Các bạn hãy áp dụng tương tự cho tần suất và doanh thu.

Tính thường xuyên

Để tạo cụm tần suất, chúng ta cần tìm tổng số đơn đặt hàng cho mỗi khách hàng. Trước tiên, hãy cùng tính xem tần suất sẽ trông như thế nào trong cơ sở dữ liệu khách hàng của chúng ta:

#get order counts for each user and create a dataframe with it
tx_frequency = tx_uk.groupby('CustomerID').InvoiceDate.count().reset_index()
tx_frequency.columns = ['CustomerID','Frequency']

#add this data to our main dataframe
tx_user = pd.merge(tx_user, tx_frequency, on='CustomerID')

#plot the histogram
plot_data = [
    go.Histogram(
        x=tx_user.query('Frequency < 1000')['Frequency']
    )
]

plot_layout = go.Layout(
        title='Frequency'
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Áp dụng cùng một logic để có các cụm tần số và gán điều này cho từng khách hàng:

#k-means
kmeans = KMeans(n_clusters=4)
kmeans.fit(tx_user[['Frequency']])
tx_user['FrequencyCluster'] = kmeans.predict(tx_user[['Frequency']])

#order the frequency cluster
tx_user = order_cluster('FrequencyCluster', 'Frequency',tx_user,True)

#see details of each cluster
tx_user.groupby('FrequencyCluster')['Frequency'].describe()

Đặc điểm của các cụm tần số của chúng ta sẽ trông giống như dưới đây:

Theo ký hiệu tương tự như các cụm lần truy cập gần đây, số tần suất cao cho biết khách hàng hoạt động tốt hơn.

Doanh thu

Tiếp đến chúng ta hãy xem cơ sở dữ liệu khách hàng sẽ trông như thế nào khi chúng ta phân nhóm chúng dựa trên doanh thu. Chúng ta sẽ tính toán doanh thu cho từng khách hàng, vẽ biểu đồ và áp dụng cùng một phương pháp phân nhóm.

#calculate revenue for each customer
tx_uk['Revenue'] = tx_uk['UnitPrice'] * tx_uk['Quantity']
tx_revenue = tx_uk.groupby('CustomerID').Revenue.sum().reset_index()

#merge it with our main dataframe
tx_user = pd.merge(tx_user, tx_revenue, on='CustomerID')

#plot the histogram
plot_data = [
    go.Histogram(
        x=tx_user.query('Revenue < 10000')['Revenue']
    )
]

plot_layout = go.Layout(
        title='Monetary Value'
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Chúng ta cũng có một số khách hàng có doanh thu âm. Hãy tiếp tục và áp dụng k-means clustering:

#apply clustering
kmeans = KMeans(n_clusters=4)
kmeans.fit(tx_user[['Revenue']])
tx_user['RevenueCluster'] = kmeans.predict(tx_user[['Revenue']])


#order the cluster numbers
tx_user = order_cluster('RevenueCluster', 'Revenue',tx_user,True)

#show details of the dataframe
tx_user.groupby('RevenueCluster')['Revenue'].describe()

Tổng điểm

Thật là đáng kinh ngạc khi chúng ta có điểm số(số cụm) cho lần truy cập gần đây cùng với tần suất và doanh thu. Hãy cùng tạo ra một điểm tổng thể từ chúng:

#calculate overall score and use mean() to see details
tx_user['OverallScore'] = tx_user['RecencyCluster'] + tx_user['FrequencyCluster'] + tx_user['RevenueCluster']
tx_user.groupby('OverallScore')['Recency','Frequency','Revenue'].mean()

Việc cho điểm ở trên, cho chúng ta thấy rõ rằng khách hàng có điểm 8 là khách hàng tiềm năng nhất và khách hàng có điểm 0 là khách hàng ít tiềm năng nhất.

Để giữ cho mọi thứ đơn giản, chúng ta sẽ quy định giá trị cho những con số này:

  • 0 đến 2: giá trị thấp
  • 3 đến 4: giá trị trung bình
  • Trên 5: giá trị cao

Chúng ta có thể dễ dàng áp dụng cách đặt giá trị này trên khung dữ liệu của mình:

tx_user['Segment'] = 'Low-Value'
tx_user.loc[tx_user['OverallScore']>2,'Segment'] = 'Mid-Value' 
tx_user.loc[tx_user['OverallScore']>4,'Segment'] = 'High-Value' 

Bây giờ hãy xem các phân đoạn của chúng ta sẽ được phân phối như thế nào trên biểu đồ phân tán:

Bạn có thể thấy các phân đoạn được phân biệt rõ ràng với nhau như thế nào về RFM. Bạn có thể tìm thấy các đoạn mã đồ thị bên dưới:

#Revenue vs Frequency
tx_graph = tx_user.query("Revenue < 50000 and Frequency < 2000")

plot_data = [
    go.Scatter(
        x=tx_graph.query("Segment == 'Low-Value'")['Frequency'],
        y=tx_graph.query("Segment == 'Low-Value'")['Revenue'],
        mode='markers',
        name='Low',
        marker= dict(size= 7,
            line= dict(width=1),
            color= 'blue',
            opacity= 0.8
           )
    ),
        go.Scatter(
        x=tx_graph.query("Segment == 'Mid-Value'")['Frequency'],
        y=tx_graph.query("Segment == 'Mid-Value'")['Revenue'],
        mode='markers',
        name='Mid',
        marker= dict(size= 9,
            line= dict(width=1),
            color= 'green',
            opacity= 0.5
           )
    ),
        go.Scatter(
        x=tx_graph.query("Segment == 'High-Value'")['Frequency'],
        y=tx_graph.query("Segment == 'High-Value'")['Revenue'],
        mode='markers',
        name='High',
        marker= dict(size= 11,
            line= dict(width=1),
            color= 'red',
            opacity= 0.9
           )
    ),
]

plot_layout = go.Layout(
        yaxis= {'title': "Revenue"},
        xaxis= {'title': "Frequency"},
        title='Segments'
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

#Revenue Recency

tx_graph = tx_user.query("Revenue < 50000 and Frequency < 2000")

plot_data = [
    go.Scatter(
        x=tx_graph.query("Segment == 'Low-Value'")['Recency'],
        y=tx_graph.query("Segment == 'Low-Value'")['Revenue'],
        mode='markers',
        name='Low',
        marker= dict(size= 7,
            line= dict(width=1),
            color= 'blue',
            opacity= 0.8
           )
    ),
        go.Scatter(
        x=tx_graph.query("Segment == 'Mid-Value'")['Recency'],
        y=tx_graph.query("Segment == 'Mid-Value'")['Revenue'],
        mode='markers',
        name='Mid',
        marker= dict(size= 9,
            line= dict(width=1),
            color= 'green',
            opacity= 0.5
           )
    ),
        go.Scatter(
        x=tx_graph.query("Segment == 'High-Value'")['Recency'],
        y=tx_graph.query("Segment == 'High-Value'")['Revenue'],
        mode='markers',
        name='High',
        marker= dict(size= 11,
            line= dict(width=1),
            color= 'red',
            opacity= 0.9
           )
    ),
]

plot_layout = go.Layout(
        yaxis= {'title': "Revenue"},
        xaxis= {'title': "Recency"},
        title='Segments'
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

# Revenue vs Frequency
tx_graph = tx_user.query("Revenue < 50000 and Frequency < 2000")

plot_data = [
    go.Scatter(
        x=tx_graph.query("Segment == 'Low-Value'")['Recency'],
        y=tx_graph.query("Segment == 'Low-Value'")['Frequency'],
        mode='markers',
        name='Low',
        marker= dict(size= 7,
            line= dict(width=1),
            color= 'blue',
            opacity= 0.8
           )
    ),
        go.Scatter(
        x=tx_graph.query("Segment == 'Mid-Value'")['Recency'],
        y=tx_graph.query("Segment == 'Mid-Value'")['Frequency'],
        mode='markers',
        name='Mid',
        marker= dict(size= 9,
            line= dict(width=1),
            color= 'green',
            opacity= 0.5
           )
    ),
        go.Scatter(
        x=tx_graph.query("Segment == 'High-Value'")['Recency'],
        y=tx_graph.query("Segment == 'High-Value'")['Frequency'],
        mode='markers',
        name='High',
        marker= dict(size= 11,
            line= dict(width=1),
            color= 'red',
            opacity= 0.9
           )
    ),
]

plot_layout = go.Layout(
        yaxis= {'title': "Frequency"},
        xaxis= {'title': "Recency"},
        title='Segments'
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Chúng ta sẽ cùng bắt tay vào việc thực hiện các phân đoạn này cùng với các chiến lược chính khá rõ ràng như:

  • Giá trị cao: cải thiện tỷ lệ giữ chân khách hàng
  • Giá trị trung bình: cải thiện tỷ lệ giữ chân khách hàng + tăng tần suất
  • Giá trị thấp: tăng tần suất

Càng vào chuyên sâu sẽ càng thú vị và hấp dẫn hơn!

Trong phần tiếp theo (phần 3), chúng ta sẽ cùng tìm hiểu về việc tính toán và cùng dự đoán giá trị vòng đời của khách hàng. Hẹn gặp lại các bạn trong phần tiếp theo nhé.

Bài viết được dịch từ đây.

Bài viết cùng seri

Bài viết liên quan

Master data là gì? Sự khác nhau giữa Master data và Transaction data

Master data là tập hợp các định danh thống nhất và các thuộc tính mở rộng. Nó mô tả các thực thể cốt lõi của doanh nghiệp bao gồm khách hàng,.......

Master data là gì? Sự khác nhau giữa Master data và Transaction data
Danh mục các loại biểu đồ trong Data Visualization

Bạn có thể tìm thấy danh sách các loại biểu đồ, nó sẽ hoạt động như một hướng dẫn đầy hữu ích giúp bạn lựa chọn được biểu đồ phù hợp với nhu cầu của bản thân....

Danh mục các loại biểu đồ trong Data Visualization
Data Analysis with Excel: Analysis ToolPak

Bộ công cụ Analysis ToolPak trên Excel sẽ giúp bạn tiết kiệm thời gian và đơn giản hóa các bước phân tích dữ liệu tài chính, thống kê ....

Data Analysis with Excel: Analysis ToolPak
Data Analysis with Excel: Solver

Excel có một công cụ được gọi là solver cung cấp các lệnh và các tính năng tùy chỉnh để giải quyết các vấn đề quyết định....

Data Analysis with Excel: Solver
Data Analysis with Excel: What-If Analysis

What-If Analysis trong Excel cho phép bạn thử các giá trị (scenarios) khác nhau cho các công thức....

Data Analysis with Excel: What-If Analysis
You've successfully subscribed to 200Lab Blog
Great! Next, complete checkout for full access to 200Lab Blog
Xin chào mừng bạn đã quay trở lại
OK! Tài khoản của bạn đã kích hoạt thành công.
Success! Your billing info is updated.
Billing info update failed.
Your link has expired.