新增['month']列,便于后续按月分析。
重新查看,此时的时间列已转换为正常格式。
由上图可知,
接下来我们用之前清洗好的字段进行数据分析。
前三个月消费订单数在10000笔左右,后续月份的平均则在2500笔。
前三个月产品购买数在20000以上,后续月份的产品购买量在6000~8000左右 。
前三个月每月的消费人数在8000-10000之间,后续月份平均消费人数在2000人不到
上述消费趋势的分析可以通过数据透视表分析(不建议数据透视表进行去重操作)
本章小结——
趋势分析:总体来看,消费总金额、消费次数、产品购买量、消费人数的趋势想似:均先上升、下跌、趋于平稳并下降。
可以看出网站的流失用户在增加,采用开源(拉新)节流(留存)的运营方式,来增加销售收入。
上一部分是按月分析,主要看趋势;本部分按用户个体分析,来看消费能力。
按用户消费金额进行降序排列,由图可知,共计约25000个用户:
启发,只要维护好这5000个用户(占比20%)就可以把业绩KPI完成70%,如果能把5000个用户运营的更好就可以占比更高。
通过以上基本数据描述分析可以清楚该网站整体的消费趋势和用户消费能力,现在进一步挖掘用户消费行为数据,通过RFM模型、生命周期等方法对用户进行分层,为后续运营管理提供依据。
首购可以进一步依渠道划分,衡量不同渠道的差异性,从而量化渠道能力,为后期渠道优化提供依据。
用户第一次购买分布,集中在前三个月(1997年1-3月);其中,在2月11日至2月25日有一次剧烈波动
由图可知,1997年1-4月新用户数量由90%跌落至80%以下;之后几个月的新用户量保持在80~82%区间。
RFM是一个经典的用户分类模型,模型利用通用交易环节中最核心的三个维度——最近消费(Recency)、消费频率(Frequency)、消费金额(Monetary)细分用户群体,从而分析不同群体的用户价值,最终达到精准营销。
RFM从3个维度、分2个等级(均值)得到8类用户分层。
通过RFM模型,把用户分为8个类别,分别给用户打标签、将客户分为重要价值、重要保持、重要挽留、重要发展、一般价值、一般保持、一般保留、一般发展8类客户。
从RFM分层可知,本网站的大部分用户为一般挽留客户(可适当放弃这部分低价值客户、也可进一步提高活跃度)、重要保持客户(企业优质的客户群,采用会员制运营)。具体运营策略依据参照如下:
为了避免划分用户群体过多(RFM从3个维度、分2个等级得到8类用户分层的数据立方),可能导致针对性的营销成本负担上升;下面将通过聚类方法,基于RFM模型划分成4类用户,更快实现后期用户管理。
显然,归一化预处理后,当n=2时,轮廓系数取最大值0.79,仅从模型聚类效果来讲分2类合适;而标准正态化预处理后显示,分4类的轮廓系数最大,达0.6964(但2-7类的轮廓系数整理差别波动不大)
参考漏斗模型,针对每个用户,按18个月内的每个月对用户情况进行分类,即新用户、活跃用户、回流用户、流失用户。
通过下面的数据透视表即可得到每个用户每个月的购买情况,从而进行转化分析。
若本月无消费(即为0)
若本月有消费(即为1)
由上表可知,每月的用户消费状态变化
这是漫长的一周,本周完成了Python的进阶模块,主要是pandas、numpy、matplotlib、seaborn、pyecharts这些模块的学习以及一个实际的案例:商品销售情况分析,之前一直觉得课程难度不够,但到这一周难度就大大提高了。尤其是案例练习中的RFM模型和用户生命周期建立,看懂不难但是自己写一直出错,在不断出错不断尝试中知识得到了积累,另外可视化部分没有什么练习题,希望后面可以加上一些这方面的练习,接下来分模块来总结一下学习的内容。
重新设置索引:df.set_index()
Series格式转换为DataFrame:df.to_frame()
文件读取:pd.read_csv(filepath, header = 0,skiprows=[1,2])
使用位置做索引:df.loc[0] 使用列表做索引:df.loc[[0,1,2]]
使用切片做索引:df.loc[0:4] 使用bool类型索引:df[df['年龄']>30]
loc 是基于索引值的,切片是左闭右闭的
iloc 是基于位置的,切片是左闭右开的
修改列索引:df.rename(columns={'姓名':'name', '年龄':'age'},inplace=True)
替换一个值:df.replace({'name':{'小明':'xiaoming'}},inplace=True)
对数据进行排序:df.sort_values('age')
累加求和:df.cumsum(0)
删除列:del df['player'] 删除行:df.drop(labels=0) labels 是行列的名字
数据拼接:pd.concat([left,right],axis=1)
# 指定列进行关联,默认是 inner join result = pd.merge(left,right,on='key')
#多个关联条件:result = pd.merge(left, right, on=['key1', 'key2'])
#左连接:result = pd.merge(left, right, how='left', on=['key1', 'key2'])
# 列名不一样的关联:pd.merge(left,right,left_on = ['key1','key2'],right_on = ['key3','key4'])
#单个分组:groups = df.groupby('district')
# 作用多个聚合函数:groups.agg([np.mean,np.sum,np.std])
# 针对具体列聚合 groups.age.agg([np.mean,np.sum,np.std])
# 不同列不同聚合函数 groups.agg({"age":np.mean,"novip_buy_times":np.sum})
分组后该列值求和显示:groups['vip_buy_times'].transform('sum')
通常用于求占比:transform(lambda x: x /sum(x))
# 填充指定值:np.full([3,4],1)
# 起始为10,5为步长,30为结尾取不到:np.arange(10, 30, 5)
#随机矩阵:np.random.random((2,3))
# 平均划分:np.linspace( 0, 2*pi, 100 )
# 类型及转换:vector.astype('float')
# 多维变一维:matrix.ravel()
# 矩阵的扩展:a = np.arange(0, 40, 10) b = np.tile(a, (3, 5)) # 行变成3倍,列变成5倍
# 水平拼接:np.hstack((a,b)) 竖直拼接:np.vstack((a,b))
# 竖直分割:np.hsplit(a,3) #水平分割:np.vsplit(a,3)
8. Select the data in rows [3, 4, 8] and in columns ['animal', 'age'].
A:df.loc[df.index[[3,4,8]],['animal','age']]
行采用位置,列采用普通索引,这里利用index函数将位置变化为具体的普通索引,再利用loc函数
19. The 'priority' column contains the values 'yes' and 'no'. Replace this column with a column of boolean values: 'yes' should be True and 'no' should be False
A1:df['priority'].replace(['yes','no'],[True,False],inplace=True) 用replace函数替换
A2:df['priority'] = df['priority'].map({'yes': True, 'no': False}) 用map函数替换
最大最小值的索引:df.idxmax、df.idxmin
找出最大最小的前N个数:nlargest()和nsmallest()
将原表分组 并设置分段区间 pd.cut(df['A'], np.arange(0, 101, 10))
resample函数 日期重采样:s.resample('M').mean()
TimeGrouper 重组:s.groupby(pd.TimeGrouper('4M')).idxmax()
split 分割函数:temp = df['From_To'].str.split('_', expand=True) True为DataFrame
两个DataFrame拼接用join:df = df.join(temp)
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
%matplotlib inline 直接显示
折线图:plt.plot(x,y,color = 'r')
柱状图:plt.bar(x,y) plt.barh(x,y) 多个bar x设置不同 堆积图 bottom设置不同
散点图:plt.scatter(x, y, c=colors, alpha=0.5, s = area)
直方图:plt.hist(a,bins= 20) bin代表分隔的最小单位
plt.legend() 显示图例
for a,b in zip(X+W[i],data[i]):
plt.text(a,b,"%.0f"% b,ha="center",va= "bottom") 添加数据标签
plt.annotate('注释文本',xy=(1, np.sin(1)),xytext=(2, 0.5), fontsize=16,arrowprops=dict(arrowstyle="->")) 添加注释文本
plt.xlabel("Group") x轴标题
plt.ylabel("Num") y轴标题
fig, axes = plt.subplots(nrows=2, ncols=2,facecolor='darkslategray') 绘制多个图形
axes[0,0] axes[0,1] axes[1,0] axes[1,1]
pylab.rcParams['figure.figsize'] = (10, 6) # 调整图片大小
动态展示图表
from pyecharts.charts import Bar
from pyecharts import options as opts
** pyecharts 绘图的五个步骤:**
创建图形对象:bar = Bar()
添加绘图数据:bar.add_xaxis(["衬衫", "毛衣", "领带", "裤子", "风衣", "高跟鞋", "袜子"])
bar.add_yaxis("商家A", [114, 55, 27, 101, 125, 27, 105])
bar.add_yaxis("商家B", [57, 134, 137, 129, 145, 60, 49])
配置系列参数:对标签、线型等的一些设置
配置全局参数:bar.set_global_opts(title_opts=opts.TitleOpts(title="销售情况"))
渲染图片:生成本地 HTML 文件 bar.render("mycharts.html") bar.render()
notebook 渲染:bar.render_notebook()
bar = (Bar()
.add_xaxis(["衬衫", "毛衣", "领带", "裤子", "风衣", "高跟鞋", "袜子"])
.add_yaxis("商家A", [114, 55, 27, 101, 125, 27, 105])
.add_yaxis("商家B", [57, 134, 137, 129, 145, 60, 49])
.set_global_opts(title_opts=opts.TitleOpts(title="某商场销售情况"))
)
bar.render_notebook()
柱状图:Bar()
条形图:bar.reversal_axis() #翻转XY轴,将柱状图转换为条形图
折线图:from pyecharts.charts import Line line=Line()
饼图:from pyecharts.charts import Page, Pie Pie()
转换日期类型:df['order_dt']=pd. to_datetime (df.order_dt,format="%Y%m%d")
将日期转换为月为单位:df['month']=df.order_dt.values. astype('datetime64[M]') 所有日期显示为当月第一天
去除日期单元值:order_diff/ np.timedelta64(1,'D')
过滤部分极值:grouped_user.sum() .query('order_products<100') .order_amount
数据透视表:rfm=df.pivot_table( index ='user_id', values =['order_products','order_amount'], aggfunc ={'order_amount':'sum','order_products':'sum'})
map() 方法是pandas.series.map()方法, 对DF中的元素级别的操作, 可以对df的某列或某多列
applymap(func) 也是DF的属性, 对整个DF所有元素应用func操作
purchase_r=pivoted_counts.applymap(lambda x: 1 if x>1 else np.NaN if x==0 else 0)
apply(func) 是DF的属性, 对DF中的行数据或列数据应用func操作,也可用于Series
apply(lambda x:x.cumsum()/x.sum()) 累计占比
apply(lambda x:x/x.sum(),axis=0) 每一列中每行数据占比
下周开始进入数据分析思维的课程,很期待后面的课程以及项目,加油!
项目背景
在面向客户制定运营策略、营销策略时,我们希望针对不同的客户推行不同的策略,实现精准化运营,以期获取最大的转化率。精准化运营的前提是客户分类。通过客户分类,对客户群体进行细分,区别出低价值客户、高价值客户,对不同的客户群体开展不同的个性化服务,将有限的资源合理地分配给不同价值的客户,实现效益最大化。在客户分类中,RFM模型是一个经典的分类模型,模型利用通用交易环节中最核心的三个维度——最近消费(Recency)、消费频率(Frequency)、消费金额(Monetary)细分客户群体,从而分析不同群体的客户价值。
项目目标
本项目借助某电商客户数据,探讨如何对客户群体进行细分,以及细分后如何利用RFM模型对客户价值进行分析。在本项目中,主要希望实现以下三个目标:1.借助某电商客户数据,对客户进行群体分类;2.比较各细分群体的客户价值;3.对不同价值的客户制定相应的运营策略。
分析过程
1.数据预览
我们的源数据是订单表,记录着用户交易相关字段
通过数据可以发现,订单状态有交易成功和退款关闭的,检查是否还有其他情况
只有这两种情况,后续清洗中需剔除退款订单。然后观察数据类型与缺失情况
订单一共28833行,没有缺失,付款日期是时间格式,实付金额、邮费和购买数量是数值型,其他均为字符串类型
2. 数据清洗
(1)剔除退款
(2)关键字段提取:提取RFM模型所需要的买家昵称,付款时间,实付金额
(3)关键字段构造:构建模型所需的三个字段,R(最近一次购买时间间隔),F(购买频次),M(平均或累计购买金额)
首先构造R值,思路是按买家昵称分组,选取付款日期最大值
为了得到最终的R值,用今天减去每位用户最近一次付款时间,就得到R值了,这份订单是7月1日生成的,所以这里我们把“2019-7-1”当作“今天”
然后处理F,即每个用户累计购买频次( 明确一下单个用户一天内购买多次订单合并为一次订单 )
思路:引入一个精确到天的日期标签,依照“买家昵称”和“日期标签”分组,把每个用户一天内的多次下单合并,再统计购买次数
最后处理M,本案例M指用户平均支付金额,可以通过总金额除以购买频次计算出来
三个指标合并
3. 维度打分
维度确认的核心是分值确定。RFM模型中打分一般采取5分制,依据数据和业务的理解,进行分值的划分
R值依据行业经验,设置为30天一个跨度,区间左闭右开
F值和购买频次挂钩,每多购买一次,分值多加一分
M值我们按照50元的一个区间来进行划分
这一步我们确定了一个打分框架,每一个用户的每个指标,都有其对应的分值
4. 分值计算
(1)算出每个用户的R,F,M分值
(2)简化分类结果
通过判断每个客户的R,F,M值是否大于平均值,来简化分类结果。0表示小于平均值,1表示大于平均值,整体组合下来有8个分组
5.客户分层
RFM经典分层按照R,F,M每一项指标是否高于平均值,把用户划分为8类
Python实现思路如下:先定义一个人群数值,将之前判断的R,F,M是否大于均值的三个值加起来
人群数值是数值类型,位于前面的0会自动略过,比如1代表001的高消费唤回客户人群,10对应010的一般客户
然后在python中定义一个判断函数,通过判断人群数值,来返回对应的分类标签
数据解读与建议:
首先查看各类用户占比情况
然后查看不同类型客户消费金额贡献占比
最后导出数据,在tableau中数据可视化展示
通过数据可视化后,我们可以发现:
1.客户流失情况严重,高消费唤回客户,流失客户占比超过总客户的50%
2.高消费唤回客户和频次深耕客户的金额总占比约66%,这两部分客户是消费的重点客户
3.流失客户和新客户的总人数占比约38%,但金额总占比只有约13%
建议:
1.针对高消费唤回客户,流失客户采用唤回策略,推送相关信息,发礼品券等挽留客户
2.针对高消费唤回客户和频次深耕客户,考虑继续挖掘其消费特性,如喜爱购买的产品,消费的时间段,后续据此加强店铺产品与时间段的改进,最大程度留住这两部分客户
3.针对流失客户和新客户金额总占比低,建议推出一些低价产品,用来拉取新客户,保证店铺的活跃性。