当前位置:   article > 正文

【RFM模型】用python实现客户价值分析_命中某个策略的客户占比python

命中某个策略的客户占比python

文章导览

        目标定义

        数据获取

        数据探索性分析

        数据清洗

        RFM模型处理

一、目标定义

这里有一个关于欧洲某商家2010年12月-2011年12月的销售数据截取的部分片段。目标是根据RF模型对顾客进行划分。

二、数据获取

​​​​​​​RFM模型训练用 - Heywhale.comhttps://www.heywhale.com/mw/dataset/623f3a0b40f3c80018378be0/file数据集已挂在和鲸社区,链接如上

三、探索性分析

        3,1 分析方向

查看数据类型、字段、大小、缺失情况,异常情况等

  1. ## 导入相关依赖
  2. import numpy as np
  3. import pandas as pd
  4. import matplotlib.pyplot as plt
  5. plt.rcParams["font.sans-serif"]=["SimHei"]
  6. plt.rcParams['axes.unicode_minus'] = False  # 解决中文显示的问题
  7. from warnings import filterwarnings
  8. filterwarnings('ignore')  # 忽略警告的问题
  9. import seaborn as sns
  10. !pip install brewer2mpl # 解决画图库尴尬的配色问题
  11. import brewer2mpl
  12. # 导入数据
  13. data = pd.read_csv("./data_sale.csv")
  14. data.head(10)

  1. # 查看基本信息
  2. data.shape
  3. data.isnull().sum()
  4. data.info()
  5. # 输出如下
  6. (541909, 8)
  7. InvoiceNo 0
  8. StockCode 0
  9. Description 1454
  10. Quantity 0
  11. InvoiceDate 0
  12. UnitPrice 0
  13. CustomerID 135080
  14. Country 0
  15. dtype: int64
  16. <class 'pandas.core.frame.DataFrame'>
  17. RangeIndex: 541909 entries, 0 to 541908
  18. Data columns (total 8 columns):
  19. # Column Non-Null Count Dtype
  20. --- ------ -------------- -----
  21. 0 InvoiceNo 541909 non-null object
  22. 1 StockCode 541909 non-null object
  23. 2 Description 540455 non-null object
  24. 3 Quantity 541909 non-null int64
  25. 4 InvoiceDate 541909 non-null object
  26. 5 UnitPrice 541909 non-null float64
  27. 6 CustomerID 406829 non-null float64
  28. 7 Country 541909 non-null object
  29. dtypes: float64(2), int64(1), object(5)
  30. memory usage: 33.1+ MB

# 数据集共54万1999条数据,8个字段
# InvoiceNo  发票编号  字符串  无缺
# StockCode  走势  字符串  无缺
# Description  描述  字符串 有缺
# Quantity  数量  数字型  无缺
# InvoiceDate  发票日期  字符串  无缺
# UnitPrice  单价  小数型  无缺
# CustomerID  顾客编号  小数型  有缺
# Country  国家  字符型  无缺

观察到Customer_ID一列数据类型是浮点小数,需要转换成字符型

  1. # 转换类型
  2. data["InvoiceDate"] = pd.to_datetime(data["InvoiceDate"])
  3. data["CustomerID"] = data["CustomerID"].astype("object",copy=False)

四、数据清洗

  1. ## 数据清洗
  2. # 去重
  3. data = data.drop_duplicates() # duplicates (n)副本 默认行数据比较取出完全相同的
  4. data.info() # 去重后还剩53万+的数据
  5. -------------------------------------
  6. # 输出
  7. <class 'pandas.core.frame.DataFrame'>
  8. Int64Index: 536641 entries, 0 to 541908
  9. Data columns (total 8 columns):
  10. # Column Non-Null Count Dtype
  11. --- ------ -------------- -----
  12. 0 InvoiceNo 536641 non-null object
  13. 1 StockCode 536641 non-null object
  14. 2 Description 535187 non-null object
  15. 3 Quantity 536641 non-null int64
  16. 4 InvoiceDate 536641 non-null datetime64[ns]
  17. 5 UnitPrice 536641 non-null float64
  18. 6 CustomerID 401604 non-null object
  19. 7 Country 536641 non-null object
  20. dtypes: datetime64[ns](1), float64(1), int64(1), object(5)
  21. memory usage: 36.8+ MB
  22. --------------------------------------
  1. # 统计异常值
  2. data.describe() # 负值明显是错误的
  3. # 查看负值的情况有多少
  4. data[data["UnitPrice"]<0]["UnitPrice"].count()
  5. data[data["Quantity"]<0]["Quantity"].count()
  6. --------------------------------------------
  7. # 输出
  8. Quantity UnitPrice
  9. count 536641.000000 536641.000000
  10. mean 9.620029 4.632656
  11. std 219.130156 97.233118
  12. min -80995.000000 -11062.060000
  13. 25% 1.000000 1.250000
  14. 50% 3.000000 2.080000
  15. 75% 10.000000 4.130000
  16. max 80995.000000 38970.000000
  17. 2
  18. 10587
  19. --------------------------------------------
  1. # 删除不符合条件的行
  2. data = data[data['UnitPrice']>=0]
  3. data = data[data['Quantity']>=0]
  4. # 缺失删除的是整行数据,删完后还剩52万6千+的数据
  5. # 统计缺失值有多少
  6. data.isnull().sum()

  1. # 统计缺失值的占比
  2. data.isnull().sum()/data.shape[0]*100 # 顾客ID一栏缺失的比较多

  1. # 删除CustomerID为空的数据
  2. data = data[~data["CustomerID"].isnull()] # 删除某些行时,可以用赋值语句。~代表取反
  3. data = data.reset_index(drop=True) # 删除之后还剩39万+行数据

五、数据分析及RFMM用户价值分析

  1. ## 数据分析
  2. # 添加一列sales
  3. data["sales"] = data["Quantity"] * data["UnitPrice"]
  4. data

  1. # 计算购买频率(每个顾客购买次数)
  2. frequency_data = data.groupby("CustomerID")["InvoiceNo"].count()
  3. frequency_data = pd.DataFrame(frequency_data)
  4. # 计算每个顾客的购买总金额
  5. frequency_data["sales"] = data.groupby("CustomerID")["sales"].sum()
  6. # 计算顾客的最近购买行为与最终日期的相隔天数
  7. frequency_data["dateDiff"] = (pd.to_datetime('2012-01-01') - data.groupby("CustomerID")["InvoiceDate"].max()).dt.days
  8. data_rfm = frequency_data
  9. # 重命名列
  10. data_rfm.columns = ["frequency","sales","datediff"]
  11. data_rfm

 

  1. ## 数据可视化
  2. # 查看数据分布
  3. sns.pairplot(data_rfm) # pairplot函数查看数据两两之间的关系

  1. # 绘制数据的直方图
  2. plt.figure(1,figsize=(12,6))
  3. n=0
  4. for x in ['frequency','datediff','sales']:
  5. n+=1
  6. plt.subplot(1,3,n)
  7. plt.subplots_adjust(hspace=0.5,wspace=0.5)
  8. sns.distplot(data_rfm[x],bins=30)
  9. plt.title('{} 直方图'.format(x))
  10. plt.show()

 

  1. ## RFM模型
  2. # 计算出划分用户的阈值,通过分布直方图可以发现该份数据不适合用中位数来分层,因此这里用均值做分层
  3. r_mean = data_rfm["datediff"].mean()
  4. f_mean = data_rfm["frequency"].mean()
  5. m_mean = data_rfm["sales"].mean()
  6. # 添加一列数据type
  7. data_rfm["cus_type"] = np.nan
  8. data_rfm

 

  1. # 编写循环填充表格type
  2. for i in range(len(data_rfm)):
  3. if data_rfm.iloc[i,0] >= f_mean and data_rfm.iloc[i,1] >= m_mean and data_rfm.iloc[i,2] < r_mean:
  4. data_rfm.iloc[i,3]="重要价值用户"
  5. elif data_rfm.iloc[i,0] >= f_mean and data_rfm.iloc[i,1] >= m_mean and data_rfm.iloc[i,2] >= r_mean:
  6. data_rfm.iloc[i,3]="重要保持用户"
  7. elif data_rfm.iloc[i,0] < f_mean and data_rfm.iloc[i,1] >= m_mean and data_rfm.iloc[i,2] < r_mean:
  8. data_rfm.iloc[i,3]="重要发展用户"
  9. elif data_rfm.iloc[i,0] < f_mean and data_rfm.iloc[i,1] >= m_mean and data_rfm.iloc[i,2] >= r_mean:
  10. data_rfm.iloc[i,3]="重要挽留用户"
  11. elif data_rfm.iloc[i,0] >= f_mean and data_rfm.iloc[i,1] < m_mean and data_rfm.iloc[i,2] < r_mean:
  12. data_rfm.iloc[i,3]="一般价值用户"
  13. elif data_rfm.iloc[i,0] < f_mean and data_rfm.iloc[i,1] < m_mean and data_rfm.iloc[i,2] < r_mean:
  14. data_rfm.iloc[i,3]="一般发展用户"
  15. elif data_rfm.iloc[i,0] >= f_mean and data_rfm.iloc[i,1] < m_mean and data_rfm.iloc[i,2] >= r_mean:
  16. data_rfm.iloc[i,3]="一般保持用户"
  17. elif data_rfm.iloc[i,0] < f_mean and data_rfm.iloc[i,1] < m_mean and data_rfm.iloc[i,2] >= r_mean:
  18. data_rfm.iloc[i,3]="一般挽留用户"
  19. data_rfm

  1. # 计算个类型用户数量并可视化
  2. Cus_type = data_rfm.groupby("cus_type")["cus_type"].count().sort_values(ascending=False)
  3. sns.barplot(Cus_type.index,Cus_type)
  4. plt.xticks(rotation=30)
  5. plt.show()

​​​​​​​ 

 

  1. # 计算不同用户的消费总额,可视化其份额比例
  2. cus_sales = data_rfm.groupby("cus_type")["sales"].sum().sort_values(ascending=False)
  3. cus_sales
  4. plt.figure(figsize=(10,10))
  5. explode01 = np.array([0.05]*8)
  6. colors01 = brewer2mpl.get_map('Set3', 'qualitative', 8).mpl_colors # 解决配色问题关键
  7. plt.pie(cus_sales,labels=cus_sales.index,autopct='%.2f%%',textprops={'fontsize':14,'color':'k'},colors=colors01,explode=explode01)
  8. plt.title('不同类型的客户销售份额',fontsize=15)
  9. plt.show()


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/780051
推荐阅读
相关标签
  

闽ICP备14008679号