python数据分析实战之用户分析及RFM模型分析

Posted 小磊要努力哟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python数据分析实战之用户分析及RFM模型分析相关的知识,希望对你有一定的参考价值。

理论基础知识可以看我之前的博客:

1、python之Numpy知识点详细总结

2、python最最最重要的数据分析工具之pandas

3、pandas之表连接与高级查询

也可以进入我的专栏:欢迎订阅哦,持续更新

python数据分析

文章目录

废话不多说了,直接开始吧!
# 导入库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime 
import warnings
from datetime import datetime


plt.style.use('ggplot')                       # 画图风格为ggplot 美化
plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体为黑体,解决图形中不显示中文的问题
plt.rcParams['axes.unicode_minus'] = False   # 正常显示负号
warnings.filterwarnings("ignore")             # 忽略警告

一、数据预处理

数据预处理分为:数据缺失值处理、数据重复值处理、数据异常值处理

1.0、数据格式转化

df = pd.read_csv('data.csv',sep=',',index_col=0)  # 读取数据 分割符',' 将第一列作为索引列
df.columns = ['订单时间','订单id','产品id','产品种类id','种类','品牌','价钱','用户id','年龄','性别','地区'] # 修改列名
df.head(2)

	订单时间	订单id	产品id	产品种类id	种类	品牌	价钱	用户id	年龄	性别	地区
0	2020-04-24 11:50:39 UTC	2294359932054536986	1515966223509089906	2.268105e+18	electronics.tablet	samsung	162.01	1.515916e+18	24.0	女	海南
1	2020-04-24 11:50:39 UTC	2294359932054536986	1515966223509089906	2.268105e+18	electronics.tablet	samsung	162.01	1.515916e+18	24.0	女	海南



# 修改字段格式
df['订单id'] = df['订单id'].astype('object')
df['产品id'] = df['产品id'].astype('object')
df['产品种类id'] = df['产品种类id'].astype('object')
df['用户id'] = df['用户id'].astype('object')
df['年龄'] = df['年龄'].astype('int')
df['订单时间'] = df['订单时间'].astype('datetime64')
df.info()

<class 'pandas.core.frame.DataFrame'>
Int64Index: 564169 entries, 0 to 2633520
Data columns (total 11 columns):
 #   Column  Non-Null Count   Dtype         
---  ------  --------------   -----         
 0   订单时间    564169 non-null  datetime64[ns]
 1   订单id    564169 non-null  object        
 2   产品id    564169 non-null  object        
 3   产品种类id  564169 non-null  object        
 4   种类      434799 non-null  object        
 5   品牌      536945 non-null  object        
 6   价钱      564169 non-null  float64       
 7   用户id    564169 non-null  object        
 8   年龄      564169 non-null  int32         
 9   性别      564169 non-null  object        
 10  地区      564169 non-null  object        
dtypes: datetime64[ns](1), float64(1), int32(1), object(8)
memory usage: 49.5+ MB

1.1、数据缺失值处理

  • 是否删除需要根据数据的重要性判断,如果用不到的字段有缺失,可以将这一列进行删除;如果字段比较重要且缺失值在20%以内也可以删除,若缺失值过多,最好不要删除否则可能会影响结果分析,我们可以看看是否可以通过原数据(的均值、众数等)进行补全;
# 从上面的结果可以知道:总数据有564169条,种类列缺失十万条数据,不能删除;品牌列缺失4万条数据,可以删除
# 缺失较多的用M替补
df['种类'] = df['种类'].fillna('M')
# 缺失较少的直接删除不影响结果
df = df[df['品牌'].notnull()]
df.info()

<class 'pandas.core.frame.DataFrame'>
Int64Index: 536945 entries, 0 to 2633520
Data columns (total 11 columns):
 #   Column  Non-Null Count   Dtype         
---  ------  --------------   -----         
 0   订单时间    536945 non-null  datetime64[ns]
 1   订单id    536945 non-null  object        
 2   产品id    536945 non-null  object        
 3   产品种类id  536945 non-null  object        
 4   种类      536945 non-null  object        
 5   品牌      536945 non-null  object        
 6   价钱      536945 non-null  float64       
 7   用户id    536945 non-null  object        
 8   年龄      536945 non-null  int32         
 9   性别      536945 non-null  object        
 10  地区      536945 non-null  object        
dtypes: datetime64[ns](1), float64(1), int32(1), object(8)
memory usage: 47.1+ MB

1.2、数据重复值处理

  • 数据不同,处理重复值的方法也不同,有些可以直接删除重复值,而有些则不能;例如在这里,存在634个重复值,由于是订单信息,可能用户购买了多份产品,后台统计订单时将其分成n条数据了,这个时候我们就不能删除了,否则影响销量结果统计。
df.duplicated().sum()  #是否存在重复值 
634
# 存在重复值,但是换个角度去想,这些重复值就是同笔订单下了多个数量的订单 

1.3、数据异常值处理

df['订单时间'].dt.year.value_counts()  
2020    535699
1970      1246
Name: 订单时间, dtype: int64
# 存在1970年的数据,原因可能是下单了但未付款,最终导致下单失败;也有可能只是数据错误。通过查看1970年的数据,发现日期仅有一个时刻的数据,因此可以确定数据出现错误,直接删除。
df = df[df['订单时间'].dt.year!=1970]
df.describe().T

         count	      mean	       std	    min	     25%	 50%    75%   	max
价钱	535699.0	214.647845	305.982110	0.0	    24.98	99.51	289.33	11574.05
年龄	535699.0	33.175421	10.127858	16.0	24.00	33.00	42.00	50.00

# 价钱的3/4位数和max差距有点打,我们可以看一下价钱>10000的是什么产品 
df[df['价钱']>10000]

订单时间	订单id	产品id	产品种类id	种类	品牌	价钱	用户id	年龄	性别	地区
1627981	2020-07-03 11:59:01	2353288509000777918	2273948305316643078	2.26811e+18	electronics.video.tv	lg	11574.05	1.51592e+18	34	男	北京
2270999	2020-09-16 06:46:10	2388440981134484484	1515966223520801280	2.3745e+18	electronics.video.tv	samsung	10416.64	1.51592e+18	34	男	上海
# 产品种类属于电子产品且属于video类,品牌为三星和lg属于高端产品 说明价钱并不异常 不需要处理

df.reset_index(drop=True,inplace=True)  # 重置索引并替换原数据

二、销量前十的品牌

brand_cnt = df.groupby('品牌')['订单id'].count().sort_values(ascending=False)

plt.figure(figsize=(10,6))
plt.bar(np.arange(10),brand_cnt[0:10],color='skyblue')
plt.title('销量前10得品牌')
plt.xticks(np.arange(10),brand_cnt[0:10].index,size=15,rotation=30)
plt.show()

三、用户画像分析

3.0、什么是用户画像呢

  • 用户画像指真实用户的虚拟代表,是建立在一系列属性数据之上的目标用户模型。说白了就是个人标签。用户画像的内容不固定,需根据行业和产品的不同所关注的用户特征也不同。对于大部分互联网公司,用户画像都会包含用户基本属性和用户行为特征。有了这些特征,我们进而挖掘产品或app等的用户特征,了解使用app或产品的使用与购物的人群,进而可以精准化营销产品,带来更多的利益。
  • 人口基本属性主要指用户本身特征:包含年龄、性别、所在省份和城市、教育程度、行业职业等。
  • 用户行为特征主要包含活跃度、忠诚度等指标,电商行业(淘宝、pdd等)购物时会有浏览、收藏、加入购物车等,从而也可以计算转化率等信息,这些也属于用于行为分析的范畴。

3.1、地区、年龄和性别分布

# 1、地区分布,按地区分布对用户计数  nunique() 去重后计数
df_area = df.groupby('地区')['用户id'].nunique().sort_values(ascending=False)
df_area

地区
广东    21382
上海    16031
北京    15928
江苏     5561
海南     5449
四川     5445
浙江     5370
湖北     5355
重庆     5342
天津     5337
湖南     5330
Name: 用户id, dtype: int64

# 2、性别分布:对性别分组,对人数计数
df_sex = df.groupby('性别')['用户id'].nunique().sort_values(ascending=False)
df_sex

性别
男    4762847235
Name: 用户id, dtype: int64

# 3、年龄段分布:将年龄切分为若干段后,再对用户进行计数
box = [10,20,30,40,50,60]
df['年龄段'] = pd.cut(df['年龄'],bins=box,right=False)  # 分箱
df_age = df.groupby('年龄段')['用户id'].nunique().sort_values(ascending=False)
df_age

年龄段
[20, 30)    27596
[30, 40)    27451
[40, 50)    27308
[10, 20)    10917
[50, 60)     2724
Name: 用户id, dtype: int64

# 4、可视化地区分布、性别分布及年龄段分布
fig = plt.figure(figsize=(12,8),facecolor='#E6E6FA')  # 设置画布大小和背景颜色

# 第一个子图:性别分布 
ax1 = fig.add_subplot(221)
patch,l_text,p_text = ax1.pie(df_sex.values,labels=df_sex.index,colors=['b','r'],autopct='%.2f%%')
for i,j in zip(l_text,p_text):  # 设置标签文字大小 l_text外面的文字标签 p_text里面的百分数 
    i.set_size(15)
    j.set_size(15)
ax1.set_title('性别分布')  # 子图标题

# 第二个子图:年龄分布
ax2 = fig.add_subplot(222)
patch,l_text,p_text = ax2.pie(df_age.values,labels=df_age.index,autopct='%.2f%%',colors=['skyblue','SpringGreen','DarkTurquoise','Gold','#FF4500'])
for i,j in zip(l_text,p_text): 
    i.set_size(12)
    j.set_size(12)
ax2.set_title('年龄分布')

# 第三个子图 :地区分布柱状图
ax3 = fig.add_subplot(212)  # 212将原来的2行2列图变为2行1列图 212 2行1列中的第二幅图
ax3.bar(df_area.index,df_area.values)

for i,j in enumerate(df_area.values): # 标签位置与显示
    plt.text(i-0.3,j+40,j)
    
ax3.set_title('地区分布')
ax3.set_ylabel('人数(人)')
# 采用ggplot风格时,会显示网格线和灰色背景
# 不显示网格线  
plt.grid(False)
# 子图的背景色透明
ax3.patch.set_alpha(0)

# 上和右边框不可见
ax3.spines['top'].set_visible(False)  
ax3.spines['right'].set_visible(False)

plt.show()

  • 从图中可以看出:
    • 年龄分布:男女比列差不多,男性比例稍高一点点。
    • 年龄分布:较多的群体是20岁到50岁的用户群体,说明这些产品深受年轻人和青年人信赖。因此,厂商可以多多研发年轻化的产品。
    • 地区分布:广东省高居第一位、其次上海市和北京市,说明北上广的用户消费的居多,消费水平也高,而且北上广还是一线城市。 其余的省份消费人数才是北上广的1/3,消费人数较少。

3.2、各年龄段的下单数量及消费金额

df_age_money = pd.DataFrame(df.groupby('年龄段')['价钱'].sum())
df_age_num = pd.DataFrame(df.groupby('年龄段')['订单id'].nunique())
age_money_num = df_age_money.merge(df_age_num,left_index=True,right_index=True)
age_money_num.columns = ['总消费金额','订单数量']
age_money_num['平均每单价钱'] = age_money_num['总消费金额']/age_money_num['订单数量']
age_money_num

               总消费金额	 订单数量	平均每单价钱
年龄段			
[10, 20)	1.237316e+07	41846	295.683236   # 各年龄段的平均消费水平还是差不太多的
[20, 30)	3.336561e+07	112086	297.678664
[30, 40)	3.211958e+07	108307	296.560528
[40, 50)	3.391897e+07	115426	293.859046
[50, 60)	3.209309e+06	11077	289.727280

# 可视化
fig = plt.figure(figsize=(15,5))
ax1 = fig.add_subplot(111)
ax1.bar(np.arange(len(age_money_num)),age_money_num['总消费金额'],color='red',width=0.2)
for i, j in enumerate(age_money_num['总消费金额']):
    plt.text(i, j, '%s' %round((j/1e7),2))
    
ax1.set_ylabel('总消费金额(千万)')   
 
ax2 = ax1.twinx() # 共用x轴
ax2.bar(np.arange(len(age_money_num))+0.2,age_money_num['订单数量'],color='skyblue',width=0.2)
for i, j in enumerate(age_money_num['订单数量']):
    plt.text(i+0.2, j, '%s' %round((j/1e4),2))

ax2.grid(False)
ax2.set_ylabel('订单数量(万)') 
plt.xticks(np.arange(len(age_money_num))+0.1,age_money_num.index)
plt.yticks(np.arange(0,130000,20000),np.arange(0,13,2))

plt.show()

  • 可以看出:无论是消费金额还是订单数量,20—50岁的用户始终是消费的重要群体。

3.3、男性女性的消费金额及下单数量

df_sex_money = pd.DataFrame(df.groupby('性别')['价钱'].sum())
df_sex_num = pd.DataFrame(df.groupby('性别')['订单id'].nunique())
sex_money_num = df_sex_money.merge(df_sex_num,left_index=True,right_index=True)
sex_money_num.columns = ['总消费金额','订单数量']
sex_money_num['平均每单价钱'] = sex_money_num['总消费金额']/sex_money_num['订单数量']
sex_money_num

	总消费金额	订单数量	平均每单价钱
性别			
女	5.710846e+07	192394	296.8307575.787818e+07	196348	294.773460

# 从性别上看,男性的总消费金额比较高,但是男性的平均消费水平较女性低,说明女生个人消费比男生高一点。

四、二八定律

  • 二八定律也称帕累托法则,即20%的人口掌握了80%的社会财富。这个结论对大多数国家的社会财富分配情况都成立。因此,该法则又被称为80/20法则。例如:当一家公司发现自己80%的利润来自于20%的顾客时,公司就该着重注意这20%的顾客,不能让他们流失掉。这样做,不但比把注意力平均分散给所有的顾客更容易,也更值得。再者,如果公司发现80%的利润来自于20%的产品,那么这家公司应该全力来销售那些高利润的产品。
user_pay Python 数据分析实战案例:基于电商销售数据的 RFM 模型构建

数据分析实战项目3:RFM用户分群

实战案例!使用 Python 进行 RFM 客户价值分析!

概念+实战讲解!一文带你了解RFM模型kaggle项目实战分享数据分析

推荐收藏一文详解数据分析经典模型RFM(附Python代码)

理论+实操|一文掌握 RFM 模型在客户数据洞察平台内的落地实战