最近学习的主要内容涉及SQL和Python。python的学习主要分为两个部分:python的基础语法,第三方库Numpy和pandas。这是第一次使用python来做项目实战。该篇主要是自己项目实战学习过程中的一个详细分析总结。
一、背景介绍
用户消费行为分析数据源真实可靠,展示的是国外用户购买CD的消费情况。其主要包含4列:用户id(id),消费的时间(order_date)、购买的产品数(num_products)以及消费的金额(amount_spend)。该篇用户消费行为分析主要分为7个部分,第1部分简要介绍项目背景;第2部分介绍整个分析的思想和流程;第3部分到第7部分则是按照第2部分的思路概述进行的详细分析过程。包含数据分析前的准备工作——导入包,数据清洗以及从三个层面进行详细数据分析。
该篇分析报告具体分析思路可参考秦璐-如何7周成为数据分析师,提取码e4r6;
数据源:国外用户购买CD数据,提取码spve。
二、整体分析思路概述
针对用户购买CD的消费数据,我们主要通过如下几个过程进行分析:
1、python包的导入
在利用python进行数据分析时,我们常用的包有:
(1)pandas:提供了很多高级的数据结构和函数,这些数据结构和函数的设计使得利用结构化、表格化数据的工作快速、简单、有表现力。pandas主要有两个数据结构:series和dataframe。
(2)numpy:Numpy是Numerical Python的简称。是 python科学计算的核心库。PYTHON里涉及到科学计算的包括Pandas,sklearn等都是基于numpy进行二次开发包装的,它的功能非常强大。
(3)matplotlib.pyplot:数据分析时可视化工具包,当然也可以使用pandas API进行绘图。
(4)seaborn:是一个更加高级的包,是matplotlib的一个抽象,就像numpy和pandas的关系,利用该包我们可以画出更多高级的图像。
可视化绘图工具包总结,提取码l7m1。
2、数据整理
数据整理是进行数据分析之前的关键步骤。数据清洗的主要任务是将脏数据清洗成可以直接处理的数据。而数据清洗的目的有2个:一是把脏数据清洗成干净的数据,二是将干净的数据进行处理便于后续分析工作的进行。数据清洗大致包含如下四步:
(1)检测缺失值:查看导入的数据是否有缺失
(2)缺失值处理:对缺失值处理主要有三种方式:直接丢掉某个变量、填充缺失值、删除缺失值所在的行。
(3)异常值处理:对某些格式、类型等异常值进行处理。
(4)数据处理:将干净的数据进行处理便于后续分析工作的进行。
3、按消费时间(月)进行分析
可以从如下几个方面进行分析:
(1)每个月的消费总金额
(2)每个月的消费次数
(3)每个月的产品购买数量
(4)每个月购买CD的人数
4、每个用户消费情况分析
可以从如下几个方面进行分析:
(1)用户消费金额、消费次数的描述统计
(2)用户消费金额和消费产品数的散点图
(3)用户累计消费金额占比(二八法则)
5、用户行为分析
(1)用户第一次消费(首购)
(2)用户最后一次消费
(3)新老客户消费比:有多少用户仅消费了一次;每月新客户占比
(4)用户分层:1)RFM,2)新客户、活跃、回流、流失
(5)用户购买周期(按订单):用户消费周期描述、用户消费周期分布
(6)用户生命周期:用户生命周期描述、用户生命周期分布
(7)用户复购率和回购率分析
接下来的章节我们将进行详细的数据分析过程。
三、导入数据分析包
在第二部分概述我们已经简要介绍过这几个包的用途。在此我们不再赘述。
四、数据整理
1、数据来源
数据源是文本格式,主要有4列——用户id(id),消费时间(order_date),购买CD数量(num_products),消费金额(amount_spend)。并且每列之间由空格分隔。
注意:每一列并没有名称标识、每列的空格间隔不确定。
(1)使用pandas方法pd.read_csv()方法将源数据导入,并给每列加上表头。
(2)通常情况下.csv文件以逗号或者制表符分隔,最初我使用的sep='\t'报错了。观察源数据发现,我们并不能确定每列间隔的空格数。因此使用正则表达式sep='\s+'。
2、数据清洗
(1)检测缺失值
可以考虑使用df.isnull()或者pd.isnull(), pd.notnull()这两个方法来检测缺失值,该方法返回的是DataFrame。由于方法count()计算的是非NA的值的个数。而根据之前导入的数据情况,我们发现总共导入了69659行数据。因此导入的数据不存在缺失值。
(2)缺失值处理
对缺失值的处理,我们通常的处理过程是先检测缺失值,然后采用删除缺失值所在的行,或者对缺失值进行填充的方式。
删除:df.dropna()
填充:df.fillna()
由于该项目不存在缺失值,因此不做任何处理。
(3)异常值处理
首先使用df.info(), df.describe()简要的观察一下数据的各项字段。注意到数据的order_date列类型有问题。因此我们对该列进行类型转化。
order_date的类型是int64,我们可以使用pd.to_datetime()方法将order_date的类型进行转化。
转化方式有两种:(1)使用pd.to_datetime()方法,(2)在读入文件是设置parse_dates字段。代码如下:
(4)数据处理
为了便于后续第五章节“按月进行数据分析”,我们需要对为原始数据增加一列“month”
五、按消费时间(月)分析
该部分我们主要从月消费总金额、月消费次数、月产品购买量、月购买CD的人数等方面做简要分析。
1、每个月的消费总金额
(1)数据处理与可视化
将数据按照month进行分组,然后对分组的消费金额amount_spend进行求和即可。
(2)分析
从可视化图形中可以得出:1997年1月到3月,这3个月消费总金额出现峰值,均值在35万左右。而后面的几个月每个月的消费总金额相对较平稳,维持在10万左右。
2、每个月的消费次数
(1)数据处理与可视化
每个月的消费次数体现在用户id出现的次数。因此将数据按照month进行分组,然后对分组的id进行计数。注意这里的重复的id是要进行重复计数的。重复id表示的是用户进行了多次消费。
(2)分析
1997年1月到3月消费总次数达到峰值,订单数为10000左右,而在后面的几个月中,每个月消费总次数比较平稳,订单数为2500左右。
3、每个月的产品购买数量
(1)数据处理与可视化
每个月产品购买数量主要体现在num_products列。因此将数据按照month进行分组,然后对分组的num_products进行求和即可。
(2)分析
1997年1月到3月购买产品数达到峰值,数量为22500左右,而在后面的几个月,每个月购买产品数比较平稳,数量为7500左右。
4、每个月购买CD的人数
(1)数据处理与可视化
每个月购买CD的人数主要体现在id这列。需要注意的是id存在重复值。由于将数据按照month进行分组后,取出id这列时返回的是series。
方法一:考虑使用drop_duplicates()方法
方法二:使用nunique()方法
上述两种方法的出来的结果是一样的。
(2)分析
1997年1月到3月购买CD的人数达到9000左右,而在后面的几个月中,每个月购买CD的人数比较平稳,人数大概为2000左右。
5、总结学习
在按时间(月)进行消费数据分析时,主要使用的DataFrame的分组方法和apply函数的灵活运用。
遗留问题:apply函数的详细总结
六、每个用户消费情况分析
这部分我们主要从用户消费金额,消费次数的描述统计、用户消费金额和消费产品数散点图、以及用户累计消费金额占比(二八法则)来进行分析。
1、用户消费金额、消费次数的描述统计
(1)描述性统计
(2)分析
1)用户平均购买了7张CD,标准差是17,说明用户购买产品数波动挺大。此外中位数为3,说明有一小部分用户购买了大量的CD,从而拉高了平均值。
2)用户消费的总金额最小值为0,这有可能是促销活动等造成的。用户平均消费金额是106,中位数是43,说明有一小部分用户购买了大量的CD,消费金额也比较大,从而拉高了平均消费金额。可知有极值干扰。
2、用户消费金额和消费产品数的散点图
(1)数据处理与可视化
方法一:使用散点图
从可视化图形中我们发现存在极值,从右下角聚集的点可知,用户消费金额与用户购买产品数存在一定的正比关系。因此我们可以考虑对极值进行处理:
方法二:使用直方图
直方图体现的单变量的数值变化。如下图展示的是每个月客户购买CD总数
从直方图可知,用户购买CD数量,绝大部分呈现集中趋势,小部分异常值干扰了判断,可以使用过滤操作排除异常值。对于直方图而言,异常值没有散点图那么明显。但是我们可以使用切比雪夫定理过滤异常值。计算95%的数据分布情况。我们知道在离平均值5个标准差的范围内会包含95%的数据。具因此7+5*17=92。也就是说我们可以通过query筛选num_porducts<92的数据。
同理对于用户每个月消费总金额的直方图以及分析与上述类似,不再赘述。
3、用户累计消费金额占比(二八法则)
秦璐-数据分析思维技巧:二八法,提取码2lbw。
帕累托法则(英语:Pareto principle,也被称为 80/20 法则、关键少数法则、八二法则)指出,约仅有20%的变因操纵着80%的局面。也就是说:所有变量中,最重要的仅有20%,虽然剩余的80%占了多数,控制的范围却远低于“关键的少数”。
举个例子:社会财富80%的财富掌握在20%的人手中,80%的人手却只掌握20%的财富。
从数据分析角度上理解,80%的数据是无用的,即数据中80%的内容是产生不了太大的价值,而只有那20%的指标才能产生最大的价值。
(1)数据处理与可视化
用户累计消费体现在amount_spend列。
(2)分析
用户消费总金额进行升序排列,由图可知,50%的用户仅贡献了15%的消费额度,而排名前5000的用户贡献了60%的消费额。
七、用户消费行为分析
在该部分我们主要从用户第一次消费(首购)、用户最后一次消费、新老客户消费占比、用户分层、用户购买周期(按订单、用户生命周期等方面进行数据分析。
1、用户第一次消费(首购)
(1)可视化
将数据根据用户id进行分组,获取每组中用户第一次订单日期。此时获得了所有用户的首购时间,然后对首购时间进行计数。可以得到在不同的时间有多少用户进行第一次消费。具体代码如下:
(2)分析
用户第一次购买,集中在前3个月(1991年1月-1997年3月),其中2月11日-2月25日有一次剧烈的波动。
2、用户最后一次消费
(1)可视化
分析思路与首购分析思路类似。
(2)分析
用户最后一次购买的分布比第一次分布广(时间跨度从1997年1月到1998年7月),大部分最后一次购买集中在前3个月,说明很多用户购买一次后就不再进行购买,随着时间的递增,最后一次购买数也在递增,消费呈现流失上升的状况。
3、新老客户消费比
(1)仅消费一次的客户
根据用户id对数据进行分组,然后获取用户第一次消费时间和最后一次消费时间。如果这两次的时间一样,说明该客户仅仅只消费了一次。
根据上述分析:说明大概有50%的客户仅消费了一次。
4、用户分层
用户分层我们主要从两个维度来进行分析:RFM;新客户、活跃、回流、流失。
4.1、RFM
(1)RFM商业模型
根据美国数据库营销研究所Arthur Hughes的研究,客户数据库中有三个神奇的要素,这三个要素构成了数据分析最好的指标:最近一次消费(Recency)、消费频率(Frequency)、消费金额(Monetary)。
根据RFM商业模型,我们需要最近一次消费、产品消费频数、消费的金额这三个指标。首先我们使用透视表来创建RFM表的雏形。即获得用户消费总金额、购买产品的总数、以及最近一次消费的时间。
我们发现order_date是时间类型。我们将用户最近一次消费与所有用户中最后一次消费的时间做个处理,得到用户最后一次消费时间距离现在最新时间的差值。
为了将order_date这种datetime64类型的数据转换成可以量化的数值型数据,我们可以使用np.timedelta64(1,'D')将其单元days去掉,变成可以处理的浮点数。此外为了与RFM模型统一,我们将amount_spend与num_products的名字做一个替换。使用rfm.rename()方法。
(2)RFM-象限法
时间“四象限”法是美国的管理学家科维提出的一个时间管理的理论,把工作按照重要和紧急两个不同的程度进行了划分,基本上可以分为四个“象限”:既紧急又重要(如客户投诉、即将到期的任务、财务危机等)、重要但不紧急(如建立人际关系、人员培训、制订防范措施等)、紧急但不重要(如电话铃声、不速之客、部门会议等)、既不紧急也不重要(如上网、闲谈、邮件、写博客等)。按处理顺序划分:先是既紧急又重要的,接着是重要但不紧急的,再到紧急但不重要的,最后才是既不紧急也不重要的。“四象限”法的关键在于第二和第三类的顺序问题,必须非常小心区分。另外,也要注意划分好第一和第三类事,都是紧急的,分别就在于前者能带来价值,实现某种重要目标,而后者不能。
秦璐-象限法,提取码hrfp。
rfm最经典的一个应用就是象限法。不同点在于RFM中划分出的是8个象限。在数学上就是将空间进行3维划分,得到8个象限。即如下图所示:需要注意的是正负半轴的定性、标签的处理。这对于我们进行下一步的分析非常重要。
1)为了做到上述的效果。首先我们需要将RFM这三列的数据划分成高于平均维度和低于平均维度的。(正半轴还是负半轴)使用如下代码可得到RFM三列的值,如果是正值则说明是在正半轴,如果是负值则表示在负半轴。
2)接下来我们需要为每个象限设置标签:如下代码利用了DataFrame的apply函数和自定义函数的灵活运用。从而得到一个含有“label”列的DataFrame。
3)根据标签将数据分配到对应的象限中。即利用label进行分组
分析:从RFM分层可知,大部分用户为重要保持客户,但是由于受到极值的影响,所以RFM的划分标准应该以业务为准:尽量用小部分的用户覆盖大部分的额度;不要为了数据好看划分等级。
4.2、新客户、活跃、回流、流失
(1)概念介绍
新用户:首购用户
活跃用户:一直在消费的用户
回流:之前没有消费或者之前有段时间没有消费了,他再次消费
流失:也称不活跃,有段时间没有消费
为了简便这里按照每个月有没有消费作为分析指标。
(2)分析过程
首先使用数据透视获得每个用户在每个月消费的次数。因为每个客户不是在18个月(1997-01到1998-06)都进行了消费。因此数据透视肯定会存在控制NaN,所以对空值用0进行填充。得到如下表:pivoted_counts
为了区分消费的用户的状态:未注册、新用户、流失(不活跃)、回流、活跃。我们先将每个月进行消费了的用户对应消费的频数进行一个状态转移,即使用0,1这两个数来表示其消费与否的状态。df_purchase
接下来为每个用户对应的这18月中的消费状态值(0或者1)进行处理,将其转变成(未注册、不活跃、新用户、回流、活跃)即(unreg, unactive, new, return, active),并用status对其状态值进行存储。转变过程逻辑为:
a)若本月没有消费0:1)若之前未注册,则依旧为未注册 ,2)若之前有消费,则为流失/不活跃,3)其他情况,为未注册
b)若本月有消费1:1)若是第一次消费,则为新用户,2)如果之前有过消费,上个月为不活跃,则为回流,3)如果上个月为未注册,则为新用户,4)除此之外,为活跃
注意:秦璐老师给的答案并不能达到预期的效果。
对每个用户每个月消费与否状态表的每行应用active_status函数即可得到我们想要的状态表purchase_status。
为了计算每个月(未注册、不活跃、新用户、回流、活跃)即(unreg, unactive, new, return, active)的用户数量,但是对于未注册的用户unreg我们不想统计,因此先将unreg未注册的用户全部用np.NaN来替代,这样使用value_counts()方法时会被自动忽略。得到如下表purchase_status_ct
(3)可视化
最终的每月分层用户数统计表purchase_status_ct的可视化
(4)每个月不同分层用户占比
如下表反应的是每个月active、new、return、unactive用户的占比
(5)分析
由上表可知,每月的用户消费状态变化:1)活跃用户,持续消费的用户,对应的消费运营的质量2)回流用户,之前不消费,本月才消费,对应的使唤回运营3)不活跃用户,对应的是流失。
遗留问题:使用SQL做用户分层分析
5、用户购买周期(按订单)
(1)用户消费周期描述、用户消费周期分布
对于用户购买周期,我们依然需要对用户进行分组。分组后用户可能会有多个订单。在Excel中可以简单的使用函数下一个单元格减去上一个单元格即可得到每个用户消费的周期。在pandas中可以使用shift()方法,即将某列数据向下平移一位。最终得到用户每个订单的时间间隔表order_diff。
order_diff是series,我们需要对其进行清洗——将单元days去掉。并汇出分布图。
订单周期呈指数分布。用户平均购买周期为68天,最大周期为533天。绝大部分用户的购买周期低于100天
6、用户生命周期
(1)用户生命周期描述
用户的生命周期在前面的分析中有涉及到:用户order_date的最小值与最大值差值。
分析:超过50%的用户声明周期都是0天,也就是说超过50%的用户仅购买了一次。
(2)用户生命周期分布
用户的生命周期在前面的分析中有涉及到:用户order_date的最小值与最大值差值。但是的出来的数据是带单位“days”。因此用之前使用过的方法np.timedelta64(1,'D')将单位去掉。得到如下分布图
分析:用户均消费134天,中位数仅为0天。并且超过50%的用户声明周期都是0天,也就是说超过50%的用户仅购买了一次。这说明用户的生命周期受到只购买一次的用户影响比较厉害(可以排除)。
因此我们提取出生命周期>0,也就是购买1次以上的用户的数据,得到如下分布图:
7、复购率和回购率分析
(1)定义
重复购买率:指消费者对该品牌产品或者服务的重复购买次数,重复购买率越多,则反应出消费者对品牌的忠诚度就越高,反之则越低。
回购率:曾经购买过的用户在某一个时期内再次购买的占比。如本月100个用户消费,下个月有30个用户再次消费,那么回购率就是30%
(2)回购率
使用之前已有的privoted_counts表。该表展示的是每个用户每个月消费的频数。
由于我们只需要每个用户每个月消费频数大于1的数据,可以采用如下处理方式:将频数大于1的设置为状态1即复购,0的设置为np.NaN即没有消费,消费1次的设置为0。如下代码使用了if的嵌套lambda x : 1 if x > 1 else (np.NaN if x == 0 else 0)
分析:复购率稳定在20%左右,因为前3个月因为有大量新用户涌入,这批用户只购买了一次,所以导致复购率降低。
(3)复购率
复购率的计算与之前的用户分层有着紧密联系。对于复购率我们只需要用户每月是否消费的状态表df_purchase,0表示该月没有消费,1表示该月有消费。
当月消费,下月再消费才算复购。如下表中0表示当月消费过,但是次月未消费,1表示当月消费了,次月也消费了,NaN表示当月没有消费。
复购率计算:
遗留问题:使用SQL做复购率和回购率分析