04/11/2019, 20:51

Marketing với Python Part 1

Hiểu dữ liệu của bạn Học cách track dữ liệu với Python 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 ...

Hiểu dữ liệu của bạn

Học cách track dữ liệu với Python

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:

  1. Hiểu dữ liệu của bạn
  2. Phân khúc khách hàng
  3. Dự đoán lợi nhuận từ khách hàng
  4. Dự đoán khách hàng rời bỏ sử dụng dịch vụ của công ty
  5. Dự đoán ngày mua hàng tiếp theo của khách hàng
  6. Dự đoán tình hình kinh doanh
  7. Kiểm thử đánh giá các chiến dịch Marketing
  8. Upsell
  9. 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 1: Hiểu dữ liệu của bạn

Để có được chiến lược hợp lý để phát triển công ty, chúng ta cần phải hiểu rõ dữ liệu mình đang có, cần tăng thông số gì: ví dụ tăng lượt truy cập, tăng khách hàng, tăng lượt đăng ký tài khoản, tăng lợi nhuận, tăng đơn hàng... Các thông số này, tùy thuộc vào sản phẩm dịch vụ của công ty, mục tiêu, và nhiều thứ khác. Ví dụ như Facebook, thì là lượng người dùng ngày.

Trong bài viết, chúng ta sẽ dùng nguồn dữ liệu Online Retail, các bạn có thể download tại đây. Với một nhà bán lẻ online, thì thông số cần quan tâm ở đây chính là doanh thu hàng tháng Monthly Revenue

Giờ xem dữ liệu đã down về có gì trong đó bằng jupyter notebook.

Doanh thu hàng tháng - Monthly Revenue

Sử dụng pandas để đọc dữ liệu từ file định dạng csv

# 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

#initiate visualization library for jupyter notebook 
pyoff.init_notebook_mode()

tx_data = pd.read_csv('data.csv')

tx_data.head(10)

Dữ liệu có dạng giống như sau: Chúng ta cần chú ý các filed sau:

  • Customer ID
  • Unit Price
  • Quantity
  • Invoice Date

Với các filed này, thông số chúng ta cần đo theo công thức:

Revenue = Active Customer Count * Order Count * Average Revenue per Order

Bây giờ, chúng ta bắt đầu tính Revenue

#converting the type of Invoice Date Field from string to datetime.
tx_data['InvoiceDate'] = pd.to_datetime(tx_data['InvoiceDate'])

#creating YearMonth field for the ease of reporting and visualization
tx_data['InvoiceYearMonth'] = tx_data['InvoiceDate'].map(lambda date: 100*date.year + date.month)

#calculate Revenue for each row and create a new dataframe with YearMonth - Revenue columns
tx_data['Revenue'] = tx_data['UnitPrice'] * tx_data['Quantity']
tx_revenue = tx_data.groupby(['InvoiceYearMonth'])['Revenue'].sum().reset_index()
tx_revenue

Xong, giờ xem doanh thu hàng tháng nó như thế nào:

Tiếp theo, trực quan hóa dữ liệu bằng hình ảnh

#X and Y axis inputs for Plotly graph. We use Scatter for line graphs
plot_data = [
    go.Scatter(
        x=tx_revenue['InvoiceYearMonth'],
        y=tx_revenue['Revenue'],
    )
]

plot_layout = go.Layout(
        xaxis={"type": "category"},
        title='Montly Revenue'
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Dựa vào biểu đồ, ta thấy doanh thu tăng từ tháng 8/2011 ( tháng 12 bị thiếu dữ liệu). Tiếp theo, xem tỷ lệ tăng doanh thu hàng tháng như thế nào (Monthly Revenue Growth Rate):

#using pct_change() function to see monthly percentage change
tx_revenue['MonthlyGrowth'] = tx_revenue['Revenue'].pct_change()

#showing first 5 rows
tx_revenue.head()

#visualization - line graph
plot_data = [
    go.Scatter(
        x=tx_revenue.query("InvoiceYearMonth < 201112")['InvoiceYearMonth'],
        y=tx_revenue.query("InvoiceYearMonth < 201112")['MonthlyGrowth'],
    )
]

plot_layout = go.Layout(
        xaxis={"type": "category"},
        title='Montly Growth Rate'
    )

fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Mọi thứ đều OK hết, ta thấy tháng 11 doanh thu tăng 36,5%. Nhưng tháng 4, doanh thu giảm, chúng ta phải tìm hiểu xem điều gì đã xảy ra trong tháng 4 này, có thể là do khách hàng ít online hơn, hoặc do ít các chuongw trình khuyến mãi, ít đơn hàng hơn... Chúng ta không thể nói được điều gì, cần phải phân tích sâu hơn nữa mới được.

Lượng khách hoạt động hàng tháng - Monthly Active Customers

Để có cái nhìn chi tiết về số liệu khách hoạt động hàng tháng, chúng ta làm theo các bước giống như tính doanh thu hàng tháng. Phần này, chúng ta chỉ dùng dữ liệu tại UK (nhiều data nhất). Chúng ta có thể tính khách hoạt động hàng tháng bằng cách đếm CustomerIDs.

#creating a new dataframe with UK customers only
tx_uk = tx_data.query("Country=='United Kingdom'").reset_index(drop=True)

#creating monthly active customers dataframe by counting unique Customer IDs
tx_monthly_active = tx_uk.groupby('InvoiceYearMonth')['CustomerID'].nunique().reset_index()

#print the dataframe
tx_monthly_active

#plotting the output
plot_data = [
    go.Bar(
        x=tx_monthly_active['InvoiceYearMonth'],
        y=tx_monthly_active['CustomerID'],
    )
]

plot_layout = go.Layout(
        xaxis={"type": "category"},
        title='Monthly Active Customers'
    )

fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Dựa vào số liệu, thấy trong tháng 4, số lượng khách hàng giảm từ 923 xuống còn 817 (-11.5%).

Số lượng đặt hàng hàng tháng - Monthly Order Count

Chúng ta cũng làm giống như trên sử dụng field Quantity

#create a new dataframe for no. of order by using quantity field
tx_monthly_sales = tx_uk.groupby('InvoiceYearMonth')['Quantity'].sum().reset_index()

#print the dataframe
tx_monthly_sales

#plot
plot_data = [
    go.Bar(
        x=tx_monthly_sales['InvoiceYearMonth'],
        y=tx_monthly_sales['Quantity'],
    )
]

plot_layout = go.Layout(
        xaxis={"type": "category"},
        title='Monthly Total # of Order'
    )

fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Đúng như dự đoán, số lượng đơn hàng trong tháng 4 giảm 8%, từ 279k xuống còn 257k.

Chúng ta thấy rằng, số lượng người dùng ảnh hưởng trực tiếp đến số lượng đơn hàng. Cuối cùng, chúng ta xem doanh thu trung bình trên mỗi đơn hàng như thế nào.

Doanh thu trung bình trên mỗi đơn hàng - Average Revenue per Order

Để có dữ liệu này, chúng ta cần tính doanh thu trung bình hàng tháng:

# create a new dataframe for average revenue by taking the mean of it
tx_monthly_order_avg = tx_uk.groupby('InvoiceYearMonth')['Revenue'].mean().reset_index()

#print the dataframe
tx_monthly_order_avg

#plot the bar chart
plot_data = [
    go.Bar(
        x=tx_monthly_order_avg['InvoiceYearMonth'],
        y=tx_monthly_order_avg['Revenue'],
    )
]

plot_layout = go.Layout(
        xaxis={"type": "category"},
        title='Monthly Order Average'
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Ta thấy, đơn hàng trung bình hàng tháng giảm vào tháng 4, nhưng nó không ảnh hưởng mấy đến doanh thu hàng tháng.

Chúng ta cần phải tìm các thông số khác ảnh hưởng đến doanh thu. Tiếp theo, chúng ta sẽ tìm hiểu thêm 2 thông số:

  • Tỷ lệ khách hàng mới - New Customer Ratio: với thông số này sẽ cho ta biết chúng ta đang mất khách hàng cũ, hoặc không thể lôi kéo khách hàng mới
  • Tỷ lệ giữ khách hàng cũ - Retention Rate: tỷ lệ khách hàng cũ tiếp tục sử dụng dịch vụ trong một khoảng thời gian nào đó.

Tỷ lệ khách hàng mới - New Customer Ratio

Trước tiên, chúng ta phải định nghĩa thế nào là khách hàng mới. Với dữ liệu đang xét, chúng ta có thể giả định khách hàng mới là khách hàng mua lần đầu trong một khoảng thời gian chỉ định trước. Chúng ta sẽ chỉ định khoảng thời gian này là 1 tháng.

Chúng ta sẽ sử dụng hàm .min() để tìm ngày mua đầu tiên của mỗi khách hàng, và tìm ra khách hàng mới dựa trên đó.

#create a dataframe contaning CustomerID and first purchase date
tx_min_purchase = tx_uk.groupby('CustomerID').InvoiceDate.min().reset_index()
tx_min_purchase.columns = ['CustomerID','MinPurchaseDate']
tx_min_purchase['MinPurchaseYearMonth'] = tx_min_purchase['MinPurchaseDate'].map(lambda date: 100*date.year + date.month)

#merge first purchase date column to our main dataframe (tx_uk)
tx_uk = pd.merge(tx_uk, tx_min_purchase, on='CustomerID')

tx_uk.head()

#create a column called User Type and assign Existing 
#if User's First Purchase Year Month before the selected Invoice Year Month
tx_uk['UserType'] = 'New'
tx_uk.loc[tx_uk['InvoiceYearMonth']>tx_uk['MinPurchaseYearMonth'],'UserType'] = 'Existing'

#calculate the Revenue per month for each user type
tx_user_type_revenue = tx_uk.groupby(['InvoiceYearMonth','UserType'])['Revenue'].sum().reset_index()

#filtering the dates and plot the result
tx_user_type_revenue = tx_user_type_revenue.query("InvoiceYearMonth != 201012 and InvoiceYearMonth != 201112")
plot_data = [
    go.Scatter(
        x=tx_user_type_revenue.query("UserType == 'Existing'")['InvoiceYearMonth'],
        y=tx_user_type_revenue.query("UserType == 'Existing'")['Revenue'],
        name = 'Existing'
    ),
    go.Scatter(
        x=tx_user_type_revenue.query("UserType == 'New'")['InvoiceYearMonth'],
        y=tx_user_type_revenue.query("UserType == 'New'")['Revenue'],
        name = 'New'
    )
]

plot_layout = go.Layout(
        xaxis={"type": "category"},
        title='New vs Existing'
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Doanh thu hàng tháng từ khách hàng mới và khách hàng cũ:

Với khách hàng cũ, ta thấy doanh thu có xu hướng tằng, nhưng ngược lại với khách hàng mới.

Tiếp theo, xem tỷ lệ khách hàng mới hàng tháng như thế nào:

#create a dataframe that shows new user ratio - we also need to drop NA values (first month new user ratio is 0)
tx_user_ratio = tx_uk.query("UserType == 'New'").groupby(['InvoiceYearMonth'])['CustomerID'].nunique()/tx_uk.query("UserType == 'Existing'").groupby(['InvoiceYearMonth'])['CustomerID'].nunique() 
tx_user_ratio = tx_user_ratio.reset_index()
tx_user_ratio = tx_user_ratio.dropna()

#print the dafaframe
tx_user_ratio

#plot the result

plot_data = [
    go.Bar(
        x=tx_user_ratio.query("InvoiceYearMonth>201101 and InvoiceYearMonth<201112")['InvoiceYearMonth'],
        y=tx_user_ratio.query("InvoiceYearMonth>201101 and InvoiceYearMonth<201112")['CustomerID'],
    )
]

plot_layout = go.Layout(
        xaxis={"type": "category"},
        title='New Customer Ratio'
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Ta thấy tỷ lệ khách hàng mới giảm như dự đoán.

Tỷ lệ giữ khách hàng cũ hàng tháng - Monthly Retention Rate

Tỷ lệ giữ khách hàng cũ nên được theo dõi chặt chẽ, bởi vì nó sẽ cho biết sản phẩm hoặc dịch vụ của công ty có phù hợp với thị trường hay không.

Monthly Retention Rate = Retained Customers From Prev. Month/Active Customers Total

Chúng ta sử dụng hàm crosstab() để tính tỷ lệ giữ khách hàng

#identify which users are active by looking at their revenue per month
tx_user_purchase = tx_uk.groupby(['CustomerID','InvoiceYearMonth'])['Revenue'].sum().reset_index()

#create retention matrix with crosstab
tx_retention = pd.crosstab(tx_user_purchase['CustomerID'], tx_user_purchase['InvoiceYearMonth']).reset_index()

tx_retention.head()

#create an array of dictionary which keeps Retained & Total User count for each month
months = tx_retention.columns[2:]
retention_array = []
for i in range(len(months)-1):
    retention_data = {}
    selected_month = months[i+1]
    prev_month = months[i]
    retention_data['InvoiceYearMonth'] = int(selected_month)
    retention_data['TotalUserCount'] = tx_retention[selected_month].sum()
    retention_data['RetainedUserCount'] = tx_retention[(tx_retention[selected_month]>0) & (tx_retention[prev_month]>0)][selected_month].sum()
    retention_array.append(retention_data)
    
#convert the array to dataframe and calculate Retention Rate
tx_retention = pd.DataFrame(retention_array)
tx_retention['RetentionRate'] = tx_retention['RetainedUserCount']/tx_retention['TotalUserCount']

#plot the retention rate graph
plot_data = [
    go.Scatter(
        x=tx_retention.query("InvoiceYearMonth<201112")['InvoiceYearMonth'],
        y=tx_retention.query("InvoiceYearMonth<201112")['RetentionRate'],
        name="organic"
    )
    
]

plot_layout = go.Layout(
        xaxis={"type": "category"},
        title='Monthly Retention Rate'
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Đầu tiên, chúng ta xem doanh thu hàng tháng từ mỗi khách hàng:

hàm crosstab() cho ta bảng thể hiện việc khách hàng sử dụng dịch vụ

Với bản này, cho ta thấy khách hàng nào sử dụng dịch vụ trong tháng (1) và không sử dụng (0)

Cuối cùng, chúng ta tính tổng số khách hàng sử dụng hàng tháng, và tỷ lệ:

Ta thấy, tỷ lệ duy trì hàng tháng tăng từ tháng 6 đến tháng 8, và trở lại bình thường sau đó.

Cuối cùng, chung ta đã biết thông số cần đo để phát triển công ty là gì, và làm sao để tính thông số đó. Bài viết tiếp theo, chúng ta sẽ phân khúc khách hàng, và tìm ra khách hàng tiềm năng nhất.

0