Marketing với Python Part 2 - Phân Khúc Khách Hàng
Phân khúc khách hàng Phân khúc khách hàng sử dụng mô hình RFM Loạt bài bài viết được thiết kế để giải thích làm thế nào sử dụng Python để phát triển công ty theo hướng phân tích dữ liệu. Các bài viết sẽ bao gồm các kỹ thuật như: lập trình python, phân tích dữ liệu, máy học. Chúng ta ...
Phân khúc khách hàng
Phân khúc khách hàng sử dụng mô hình RFM
Loạt bài bài viết được thiết kế để giải thích làm thế nào sử dụng Python để phát triển công ty theo hướng phân tích dữ liệu. Các bài viết sẽ bao gồm các kỹ thuật như: lập trình python, phân tích dữ liệu, máy học. Chúng ta sẽ đi tìm hiểu các chủ đề sau:
- Hiểu dữ liệu của bạn
- Phân khúc khách hàng
- Dự đoán lợi nhuận từ khách hàng
- Dự đoán khách hàng rời bỏ sử dụng dịch vụ của công ty
- Dự đoán ngày mua hàng tiếp theo của khách hàng
- Dự đoán tình hình kinh doanh
- Kiểm thử đánh giá các chiến dịch Marketing
- Upsell
- A/B testing
Bài viết sử dụng Python và Pandas, nên nếu các bạn chưa biết thì có thể tìm hiểu trước Python và Pandas nhé. Hoặc các bạn làm Marketing chưa biết code, vẫn có thể đọc qua bài viết để hiểu ý tưởng sử dụng dữ liệu hiện có để phát triển công ty.
Sometimes you gotta run before you can walk - Tony Stark
Yêu cầu hệ thống: cài Jupyter Notebook và Python
Phần 2: Phân khúc khách hàng
Ở bài viết trước, chúng ta đã tìm hiểu, phân tích dữ liệu của một công ty bán lẻ trực tuyến và tìm ra các yếu tố ảnh hưởng đến doanh thu lợi nhuận của công ty (vd: tỷ lệ khách hàng cũ tiếp tục sử dụng dịch vụ của công ty - Retention Rate ). Chúng ta đã biết cách sử dụng Python và Pandas thống kê và tìm hiểu các yếu tố đó. Bây giờ, chúng ta sẽ tập trung vào khách hàng và tìm cách phân loại khách hàng theo nhóm để phục vụ cho nhu cầu marketing sau này.
Chúng ta cần phải thực hiện công việc phân nhóm, phân loại khách hàng..., bởi vì chúng ta không thể đối xử tất cả khách hàng giống nhau: ví dụ, mỗi chiến dịch marketing sẽ nhắm vào một phân khúc khách hàng khác nhau, nội dung khách nhau, kênh phân phối chiến dịch khách nhau...
Khi khách hàng đến với chúng ta, họ có các nhu cầu riêng biệt, chúng ta phải tìm cách phản hồi và hành động dựa trên các nhu cầu này đối với từng khách hàng riêng biệt.
Có rất nhiều cách, phương thức để phân loại khách hàng. Trong bài viết này, chúng ta sẽ phân loại khách hàng dựa trên mô hình RFM, một mô hình rất hay được sử dụng để đo tỷ lệ sử dụng dịch vụ của khách hàng, đồng thời có thể được sử dụng để đánh giá sản phẩm dịch vụ của công ty có phù hợp với thị trường hay không.
RFM là các từ viết tắt của Recency - Frequency - Monetary Value, dịch theo tiếng Việt có nghĩa là: hành động gần đây nhất, bao nhiêu lần và có giá trị bao nhiêu. Nếu xét trong ngữ cảnh của một nhà bán lẻ, dựa trên các hóa đơn bán hàng, thì các thông số này sẽ là: lần mua gần nhất, bao nhiêu lần mua, và giá trị tổng các lần giao dịch là bao nhiêu.
Chúng ta sẽ phân nhóm khách hàng theo các phân khúc sau:
- Giá trị thấp (low value): là nhóm khách hàng mua ít hơn nhóm khác, ít thường xuyên sử dụng dịch vụ, và mang về lợi nhuận cho công ty thấp.
- Giá trị trung bình (Mid value): các chỉ số mua sắm, sử dụng dịch vụ và lợi nhuận mang về cho công ty đề ở mức trung bình.
- Giá trị cao (hight value): đây là phân khúc khách hàng quan trọng nhất, mang về lợi nhuận cao cho công ty và thường xuyên sử dụng dịch vụ nhất.
Để phân khúc khách hàng theo mô hình RFM, chúng ta cần phải tính các thông số Recency, Frequency and Monetary Value và sử dụng phương pháp máy học không giám sát (unsupervised machine learning) để phân nhóm gôm cụm khách hàng. Trong bài viết, mình sẽ sử dụng nhiều thuật ngữ tiếng anh, vì nếu dịch sang tiếng Việt sẽ rất dài dòng, mong các bạn thông cảm nhé.
Recency - R Để tính thông số R này, chúng ta cần tìm ra ngày mua gần đây nhất của khách hàng và số ngày không sử dụng dịch vụ của họ - inactive days (tính từ thời điểm mua gần nhất đến thời điểm đang xét). Sau khi có con số inactive days của mỗi khách hàng, chúng ta sẽ áp dụng thuật toán phân nhóm gôm cụm K-means để tính điểm recency
Bài viết sẽ tiếp tục sử dụng dữ liệu giống như bài trước, các bạn có thể download tại đây. Vẫn tiếp tục sử dụng các dữ liệu phát sinh từ UK
# 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)
Tính recency (R)
#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)
Tiếp tục, chúng ta xem xét dữ liệu Rencency phân phối như thế nào: mean, min, max, count and % bằng hàm describe()
Chúng ta có thể thấy rằng, nếu tính trung bình cho tập dự liệu recency đang có, thì con số này là 90 ngày (mean), và theo số phần trăm, thì có đến 50% dữ liệu khách hàng có số recency là 49 ngày.
Cũng với đoạn code trên, cho ta biểu đồ phân bổ số liệu Recency của khách hàng
Giờ sẽ đến phần chính của bài, chúng ta sẽ áp dụng thuật toán phân nhóm K-means để tính điểm recency. Nhưng trước tiên, thì chúng ta phải cho thuật toán biết cần phân bao nhiêu nhóm là hợp lý. Để tìm ra con số này, ta áp dụng phương thức Elbow. Có thể hiểu đơn giản là, phương thức Elbow sẽ cho ta con số cụm tối ưu nhất cho thuật toán K-means.
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()
Chúng ta thấy rằng số lương cụng tối ưu nhất là 3. Nhưng chúng ta có thể lựa số cụm nhỏ hoặc lớn hơn 3, tùy theo yêu cầu kinh doanh. Chúng ta chọn số cụm là 4 cho bài viết 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 đã phân cụm khách hàng, và chỉ định mỗi khách hàng sẽ thuộc 1 cụm khác nhau và tập dữ liệu tx_user.
Chúng ta có thể thấy, cụm 1 là cụm tập khách hàng có recency tốt nhất (càng nhỏ càng tốt), có nghĩa là đây là cụm có khách hàng hoạt động gần đây nhất(mua hàng...)
Chúng ta thực hiện thêm hàm order_cluster() để sắp xếp lại các cụm khách hàng theo theo hướng cụm 0 là tệ nhất -> cụm 3 là tốt nhất...
Tuyệt vời, cụm 3 là cụm có tập khách hàng hoạt động gần đây nhiều nhất.
Tiếp theo, tính toán Frequency và Monetary Value cũng thực hiện giống như trên
Frequency - F
Để phân cụm khách hàng theo F, ta cần phải tìm tổng số đơn hàng của mỗi khách hàng.
#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)
Phân loại khách hàng theo F
#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()
F càng lớn, thì khách hàng đó càng tốt cho công ty (mua nhiều)
Monetary Value - M
Chúng ta sẽ phân nhóm khách hàng theo M. Đầu tiên chúng ta tính M cho mỗi khách hàng, vẽ biểu đồ, và gom cụm giống như các bước tính F
#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 thấy cũng có nhiều khách hàng mang về cho công ty lợi nhuận âm. Tiếp tục gôm cụm:
#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 RFM
Cuối cùng, chúng ta đã có điểm RFM (theo cụm). Tiếp theo chúng ta sẽ tính tổng các điểm này:
#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()
Theo bảng trên, khách hàng có điểm 8 là khách hàng tốt nhất. Để đơn giản, chúng ta sẽ phân tiếp thành 3 nhóm khách hàng:
- 0 to 2: Low Value
- 3 to 4: Mid Value
- 5+: High Value
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'
Tiếp theo, vẽ hình để xem sự phân bố tập khách hàng như thế nào:
#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(awidth=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(awidth=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(awidth=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(awidth=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(awidth=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(awidth=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(awidth=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(awidth=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(awidth=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)
Từ đây, chúng ta có thể lên chiến lược, hành động với các tập khách hàng này:
- High Value: Improve Retention
- Mid Value: Improve Retention + Increase Frequency
- Low Value: Increase Frequency
Sau bài viết này, hy vọng các bạn có chiến lược marketing phù hợp với từng nhóm khách hàng khác nhau. VD: nhóm khách hàng cần quan tâm nhiều hơn, nhóm khách hàng cần khuyến mãi, tặng coupon giảm giá, nhóm khách hàng cần cân nhắc sử dụng sản phẩm mới của công ty với giá đặc biệt ưu đãi...
Trong phần tiếp theo, chúng ta sẽ tìm hiểu tiếp một thông số quan trọng CLV (Customer Lifetime Value), tính toán lợi nhuận khách hàng mang về cho công ty
Lifetime Value: Total Gross Revenue - Total Cost