项目概述
本项目对2020年某家公司各个门店的电子产品(手机,平板等)的销售数据进行消费者画像分析,并对会员采用RFM模型进行分析。
环境
win10,Python 3 ,jupyter notebook
目录
正文
一、数据处理
1.数据概览
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import re
import warnings
warnings.filterwarnings('ignore')
%matplotlib inline
plt.rcParams['font.sans-serif']=['Microsoft YaHei'] #中文用微软雅黑字体
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
df_u = pd.read_csv('电子产品销售分析.csv')
先看一下前面几行的数据和数据基本情况
df_u.head()
df_u.info()
数据维度:564169 行 X 12 列
缺失字段:category_code,brand
数据类型: 3个64位整型, 4个64位浮点型,5个python对象
查看整型和浮点型的描述性统计
df_u.describe()
可以发现
- Unnamed: 0 这一列基本没有意义,可以删去
- 一共有12列,其中 category_code 和 brand两列有缺失值,brand用'no_brand' 填充空值,category_code 用'no_category'填充空值
- event_time 太长,可以将其转成datetime格式,只保留日期,发现event_time 列有1970年的数据,应是输入错误,要更改为2020年
- 购买电子产品的客户平均年龄在33岁左右,手机平均价格在208美元附近,中位数是87.9美元
再查看python对象的描述性统计
df_u[['event_time','category_code','brand','sex','local']].describe()
初步发现:
- 手机的销量最大,占全部电子商品的1/4左右;
- 牌子为samsung的商品销量最多;
- 男性顾客比女性顾客多;
- 在区域分布上,广东省的顾客最多
2.数据清洗
del df_u['Unnamed: 0']
df_u['brand'].fillna('no_brand',inplace = True) #brand的缺失值用'no_brand'填充
df_u['category_code'].fillna('no_category',inplace = True) #brand的缺失值用'no_category'填充
df_u = df_u.drop_duplicates('order_id') #去掉重复的订单
df_u['event_time'] = df_u['event_time'].str.replace('1970','2020')
df_u['event_time'] = pd.to_datetime(df_u['event_time']).dt.to_period('D')
df_u['month'] = df_u['event_time'].dt.month
df_u = df_u.set_index('event_time',drop = False)
df_u.head()
查看更改之后的数据
二、消费人群分析
1.根据下单数量的多寡将用户分成两类
用user_record记录每个用户下单的数量
df = df_u
user_record=df.groupby('user_id')['order_id'].count().sort_values(ascending=False)
user_record.head(10) #看一下前十行
user_record.describe()
data1=pd.cut(user_record,bins=20).value_counts() #分成20组
print(data1)
fig=plt.figure(figsize=(20,8),dpi=80)
plt.rcParams['font.sans-serif']=['SimHei']
plt.xlabel('订单量',fontsize=16)
plt.ylabel('购买人数',fontsize=16)
plt.xticks(fontsize=16)
plt.yticks(fontsize=16)
plt.title('购买人数随订单量分布',fontsize=20)
data1.plot.bar()
plt.show()
- 用户的订单数分布差异极大,最大订单数为666,但是超过75%的用户订单数都在3以内
- 通过对数据分组,发现绝大多数的用户订单数都在30以内;根据数据的分布情况以及实际消费场景,我们按照30为界限对用户进行分类:A类客户(总订单数>=30),B类客户(总订单数<30)
- A类客户均为高频稳定消费群体,且群体总量较小,所以本次分析的重点会聚焦 B 类客户
#将客户分成a、b两组
df_b = df.loc[df['user_id'].isin(user_record[user_record<30].index)]
df_b['user_level']= 'B'
df_a=df.loc[df['user_id'].isin(list(df_b['user_id']))]
df_a['user_level']='A'
df_ab = pd.concat([df_a,df_b])
我们再画出A,B两类客户的占比图以及订单数订单额的柱状堆叠图
plt.rcParams['font.sans-serif']=['SimHei']
fig,axs = plt.subplots(1,2 ,figsize=(12,5),dpi=90)
df_ab.groupby('user_level')['user_id'].nunique().plot(kind='pie',title='AB两类客户占比图',ax=axs[0],autopct='%.2f%%',ylabel='',wedgeprops={'width':0.3})
ax1 = pd.concat([pd.DataFrame({'A':[0]}),df_ab.groupby('user_level').agg({'order_id':pd.Series.count}).T],axis=0).plot(kind = 'bar',legend=False,ax=axs[1],stacked=True,xlabel='',title='AB两类客户订单数,订单额堆叠图')
pd.concat([df_ab.groupby('user_level').agg({'price':np.sum}).T,pd.DataFrame({'A':[0]})],axis=0).plot(kind = 'bar',ax=ax1.twinx(),stacked=True,xlabel='').set_xticklabels(['订单额','订单数'])
plt.show()
B类用户占比98.91%,并且订单额和订单数占大部分;A类用户情况较为特殊,数量少但是一次性购买的产品数多,应该是经销商之类的客户。下面我们重点分析B类消费者。
2.按照地域进行分析
import seaborn as sns
fig,axs = plt.subplots(1,2 ,figsize=(12,5),dpi=120)
df_b.groupby('local')['user_id'].nunique().plot(kind='pie',title='各个省份用户数占比图',ax=axs[0],autopct='%.0f%%',ylabel='',wedgeprops={'width':0.3})
df_b.groupby('local')['user_id'].nunique().sort_values().plot(kind='barh',title='各个省份用户数条形图',ax=axs[1],xlabel='省份').grid(alpha=0.3)
plt.show()
消费者主要分布在广东、上海、北京这些经济发达的区域,营销策略可以重点向一线城市倾斜
3.按照年龄、性别进行分析
fig=plt.figure(figsize=(10,5),dpi=120)
df_b.groupby('sex')['user_id'].nunique().plot(kind='pie',title='用户性别占比图',autopct='%.2f%%',ylabel='',wedgeprops={'width':0.3})
plt.show()
fig,axes=plt.subplots(1,2,figsize=(10,5),dpi=120)
df_b['age']=df_b['age'].astype(int)
df_b['agegroup']=pd.cut(df_b['age'],bins=8)
df_b.groupby('agegroup')['user_id'].nunique().sort_values().plot(kind='pie',title='用户年龄段占比图',ax=axes[0],autopct='%.2f%%',ylabel='',wedgeprops={'width':0.3})
df_b.groupby('agegroup')['user_id'].nunique().sort_values().plot(kind='barh',title='用户年龄段条形图',ax=axes[1]).grid(alpha=0.3)
plt.subplots_adjust(wspace=1)
plt.show()
- 客户的男女比例基本相当;
- 各个年龄段购买电子产品的人数都在1万人以上,占比差别不大;
- 个别年龄段达到了1.3万人以上,可以重点关注这些年龄段
4.按照产品进行分析
plt.rcParams['font.sans-serif']=['SimHei']
fig,axs=plt.subplots(1,2,figsize=(10,5),dpi=120)
df_b.groupby('brand')['price'].sum().sort_values(ascending=False).head(10).plot(kind='bar',title='各大品牌销售额统计图',xlabel='brand',ax=axs[0])
df_b.groupby('brand')['price'].sum().sort_values(ascending=False).head(10).plot(kind='pie',autopct='%.1f%%',title='各大品牌销售额扇形图',ylabel='',ax=axs[1])
plt.show()
对每个品牌的销售额进行统计排序后,呈现前十的大品牌的销售额,我们可以发现apple和samsung 这两个品牌有绝对的优势,总共占前十大品牌销售额的66.8%
我们再细分看一下前十大电子产品的销售额
%matplotlib inline
fig,axs=plt.subplots(1,2,figsize=(12,5),dpi=120)
df_ab.groupby(['category_code','user_level'])['price'].sum().unstack().sort_values(by=['B'],ascending=False).head(10).plot(stacked=True,kind='bar',title='前十大电子产品销售额柱状图',ax=axs[0],xlabel='')
phone= df_b.loc[df_b['category_code']=='electronics.smartphone']
phone.groupby('brand')['price'].sum().sort_values(ascending=False).head(6).plot(kind='pie',ax=axs[1],ylabel='',autopct='%.1f%%',title='智能手机各大品牌占比图')
plt.show()
- 我们可以发现智能手机的销售额最多,是笔记本的3倍左右
- 再单独看一下智能手机中是哪些品牌占的市场份额大,发现还是apple和samsung这两个牌子,建议门店可以多置备这两个牌子的手机
5.按照时间进行分析
fig=plt.figure(figsize=(12,5),dpi=120)
ax1 = df.groupby('month')['user_id'].nunique().rename('人数').plot(title='消费金额、人数随时间变化图',ylabel='人数',xlabel='月份',legend=1)
df.groupby('month')['price'].sum().rename('消费总金额').plot(ax=ax1.twinx(),color='orange',figsize=(14,7),ylabel='消费金额',legend=True,xlabel='').legend(loc=2)
plt.xticks(range(1,13))
plt.show()
可以发现,7-9月份是消费的高峰期,建议暑期做好手机、笔记本电脑等产品的营销。
三、RFM分析
b_r = df_b.groupby('user_id')['event_time'].min().map(lambda i : pd.to_datetime('2020-11-21').to_period('D')-i)
R = b_r.astype('str').map(lambda i: re.compile(r'\d*').findall(i)[1])
R.loc[b_r.astype('str').map(lambda i: re.compile(r'\d*').findall(i)[1])=='']=1
R = R.astype('int32')
F = df_b.groupby('user_id')['order_id'].count()
M = df_b.groupby('user_id')['price'].sum()
def RFM(x):
r='1' if x[0]<= 30 else '0' # 最近购物天数在30天以内
f='1' if x[1]>= 3 else '0' # 累计购物次数大于2次(均值)
m='1' if x[2]>=1257 else '0' # 累计消费金额大于1257(均值)
return dic_rfm[r+f+m]
dic_rfm ={
'111':'重要会员:倾斜更多资源,VIP服务,个性化服务,附加销售',
'011':'重要唤回会员:DM营销,提供有用的资源,通过新的商品召唤回',
'101':'重要深耕会员:交叉销售,制定会员忠诚度计划,推荐其他商品',
'001':'重要挽留会员:重点联系或摆放,提高留存率',
'110':'潜力会员:向上营销,销售价值更高的商品',
'100':'新会员:提供免费试用,提高会员兴趣,创建品牌知名度',
'010':'一般维持会员:积分制,分享宝贵资源,以折扣推荐热门商品',
'000':'低价值会员:恢复会员兴趣,否则暂时放弃'}
b_rfm = pd.concat([R,F,M],axis=1).apply(RFM,axis=1)
B_RFM = pd.concat([b_rfm.map(lambda i: i.split(':')[0]).rename('会员类型'),b_rfm.map(lambda i: i.split(':')[-1]).rename('营销策略')],axis=1)
fig,axs = plt.subplots(1,2,figsize=(16,6),dpi=120)
B_RFM.groupby('会员类型')['营销策略'].count().plot(kind='pie',title='B类会员-类型占比',autopct='%.0f%%',ax=axs[1],wedgeprops={'width':0.3},ylabel='')
B_RFM.groupby('会员类型')['营销策略'].count().sort_values().plot(kind='barh',title='B类会员-类型分布',xlabel='',ax=axs[0],grid=1)
plt.show()
建议:
1.门店可以根据RFM类型将B类消费者分类,分别进行不同的营销行为,以达到效率最大化
2.门店有较多的重要唤回会员,占15%,潜在价值较高,可以重点跟踪