用Python分析用户消费行为

本文是《如何在七周内成为数据分析师》的第23篇教程。如果你想理解写作的初衷,你可以先阅读七周的指南。温馨提示:如果你已经熟悉了Python,不用看这篇文章,也不用只选部分。

今天用Python分析用户的消费行为,内容会更扎根,难度会稍微增加。这也是七周内成为数据分析师的最后一个教程。以前的知识点将在这里串联起来。

数据来源CDNow网站用户购买明细。共有用户ID,四个字段:购买日期、购买数量和购买金额。我们通过案例数据完成基本数据分析报告。

加载包和数据,文件是txt,用read_table方法打开,因为原始数据不包含表面,所以需要给予。字符串是空格分割,使用s 表示匹配任何空白符。

观察数据,order_dt表示时间,但现在它只是一系列数字的组合,没有时间意义。购买金额是一个小数字。值得注意的是,用户可以在一天内购买多次,用户ID为2的用户就在1月12日买了两次,这个细节不要遗漏。

用户平均购买每个订单2.4商品,标准差在2.3,有点波动。中位数为2件商品,75件商品为3件,表明大多数订单的购买量不多。最大值为99件,数量相对较高。购买金额几乎相同,大多数订单都集中在小额。

一般来说,消费数据分布是长尾形式。大多数用户都很小,但少数用户贡献了大部分收入,通常被称为28。

没有空值,数据非常干净。接下来,我们将转换时间数据类型。

pd.to_datetime将特定的字符串或数字转换为时间格式for ** t参数用于匹配。比如19970101,%Y如果匹配前四位数字1997,y小写只匹配两位数字97%m匹配01,%d匹配01。

另外,小时是%h,分钟是%M,注意与月大小写不一致,秒为%s。若是1997-01-01这种形式是%Y-%m-%d,以此类推。

astype也可以转换时间格式,比如[M]转化为月份。我们把月份作为消费行为的主要事件窗口,取决于消费频率。

上图显示了转换后的格式。月份仍显示日,成月初的形式。

pandas有专门的时间序列方法tseries,可用于时间偏移,也是处理时间类型的好方法。时间格式也可以作为索引,广泛应用于金融、金融等领域,这里就不多描述了。

以上消费行为数据粒度为每个订单,我们将其转换为每个用户。

用groupby创建一个新对象。

从用户的角度来看,每个用户平均购买7张CD,大多数用户购买1033个,属于狂热用户。用户平均消费金额(客户单价)为100元,标准差为240元。结合分数和最大值,平均值接近75分,必须有少数高消费用户。

接下来按月分析维度。

每个月按月统计CD销量。从图中可以看出,前几个月的销量非常高。数据异常。后期销量非常稳定。

金额也呈现出早期销量大、后期稳步下降的趋势。为什么会出现这个原因?我们假设用户有问题,早期用户有异常值,第二个假设是各种促销营销,但这里只有消费数据,无法判断。

绘制每个订单的散点图。从图中可以看出,订单消费金额和订单商品数量是有规律的,每件商品大约10元。订单极值较小,只有少数超过1000。显然,这不是异常波动的罪魁祸首。

画用户的散点图,用户也比较健康,比订单更有规律。因为这是CD网站销售数据,商品相对单一,金额与商品量的关系呈线性,离群点很少。

消费能力特别强的用户有,但数量不多。用直方图观察更好。

plt.subplot用于绘制子图,子图用数字参数表示。121表示分成1*2图片区域占据第一个,即第一行第一列,122表示占据第二个。figure是尺寸函数,为了容纳两张子图,宽度可以设置得更大。

从直方图来看,大部分用户的消费能力确实不高,高消费用户在图中几乎看不到。这确实符合消费行为的行业规律。

观察用户消费金额和购买量后,再看消费时间节点。

用groupby函数将用户分组,并要求月份的最小值,最小值是用户消费行为中的第一次消费时间。ok,结果,所有用户的第一次消费都集中在前三个月。我们可以认为,案例中的订单数据只选择了用户在18个月内的消费行为。

观察用户的最后一次消费时间。大部分数据仍集中在前三个月。在后续时间内,用户仍在消费,但消费缓慢。

解释了异常趋势的原因,并进一步细分了消费数据。我们需要明确的是,这只是一些用户的订单数据,因此有一定的局限性。在这里,我们将数据上的用户定义为新客户。

接下来,分析消费中的回购率和回购率。首先,透视用户消费数据。

在pandas在数据透视中,有一个特殊的函数pivot_table,功能非常强大。pivot_table参数中,index设置数据透视后的索引,column简而言之,设置数据透视后的列,index是你想要的,column是想要的列。在这种情况下,我希望每个用户户每月的订单量,所以user_id是index,month是column。

values计算哪个值,aggfunc用什么方法?所以这里用。values=order_dt和aggfunc=count,统计里order_dt出现次数,即多少订单。

使用数据透视表需要明确结果。有些用户在某个月没有消费,会使用它NaN表示,这里用fillna填充。

月是生成的数据透视1997-01-01 00:00:00表示丑陋。优化成标准格式。

首先,要求回购率。回购率的定义是在一定时间窗口内消费两次或两次以上的用户占总消费用户的比例。这里的时间窗口是每月一次。如果一个用户在同一天下了两个订单,他也将被视为回购用户。

转换数据,将消费两次以上记为1,消费一次记为0,不记为消费NaN。

apply ** p针对DataFrame所有数据lambda判断需要两个,因为它涉及多个结果if else,记住,lambda没有elif的用法

用sum和count回购率可以通过相除来计算。因为这两个函数都会被忽略NaN,而NaN没有消费的用户,count无论是0还是1,都会统计,所以是消费用户总数,sum求和计算了两次以上的消费用户。这里用巧妙的替代方法计算回购率,SQL也可以在中间使用。

从图中可以看出,回购率处于早期阶段。由于大量新用户加入,新客户的回购率不高。例如,1月份新客户的回购率只有6%左右。在后期,此时的用户是大浪淘沙的剩余老客户,回购率相对稳定,约为20%。

单看新客和老客,回购率差距在三倍左右。

接下来,计算回购率。回购率是在一定时间窗口内消费的用户,在下一次窗口仍然消费的比例。我在1月份消费了1000名用户,其中300名仍在2月份消费,回购率为30%。

由于设计了横向跨时间窗口的对比,因此很难计算回购率。

将消费金额进行数据透视,这里作为练习,使用了平均值。

再次用apply ** p lambda转换数据,只要有购买,记为1,反之为0。

新建判断函数。data输入数据,即用户是否在18个月内消费,status后续用于保存用户是否回购的字段是空列表。

因为有18个月,每个月都要做一次判断,需要循环。if主要逻辑是,如果用户本月消费,下个月消费,记录为1,没有消费为0。如果这个月没有消费,那就是NaN,排除后续统计。

用apply函数应用于所有行,以获得预期的结果。

最后的计算和回购率差不多,用count和sum从图中可以看出,用户的回购率高于回购率,约为30%,波动性强。新用户的回购率约为15%,与老客户没有太大区别。

综合分析购率和回购率的综合分析,可以得出结论,新客户的整体质量低于老客户,老客户的忠诚度(回购率)表现良好,消费频率是CDNow网站的用户消费特征。

接下来,根据用户的消费行为,我们将用户分层分为几个维度:新用户、活跃用户、非活跃用户和回流用户。

新用户的定义是第一次消费。活跃用户是老客户,在某个时间窗口消费。不活跃的用户是没有在时间窗口消费的老客户。回流用户不在上一个窗口消费,而在当前时间窗口消费。以上时间窗口按月统计。

例如,如果一个用户在1月份第一次消费,他在1月份的分层是新用户;他在2月份的消费国是活跃用户;3月份没有消费,此时不活跃用户;4月份再次消费,此时是回流用户,5月份还是消费,是活跃用户。

分层将涉及复杂的逻辑判断。

函数写得更复杂,主要分为两部分,以本月是否消费为界。这个月没有消费,但也要判断他是否是新客户,因为有些用户在3月份成为新客户,所以他甚至不应该在1月或2月使用新客户unreg表示。如果是老客户,那就是老客户。unactive。

如果这个月有消费,你需要判断它是否是第一次消费,以及最后一个时间窗口是否消费。你可以调试几次来理顺逻辑关系,并对用户进行分层。逻辑真的不简单,这里只是简化版本。

从结果来看,我们已经计算出了用户每月的分层状态和变化。我是根据透视宽度计算的。事实上,还有另一种写作方法。我只提取时间窗口中的数据与上一个窗口进行比较和判断,并将其包装成函数进行循环。ETL的增量更新。

unreg排除状态,是的「未来」作为新客户,我们可以这样计数。转换为不同层次的月度统计。

生成面积图,丑陋。因为它只是用户在一定时间内消费的后续行为,蓝色和灰色 ** 域不能看。只看紫色回流和红色活跃两个层次,用户数量相对稳定。这两个层次的结合是消费者用户的比例有新客户)。

用户回流率占5%~8%,有下降趋势。所谓回流率,就是回流用户在总用户中的比例。另一个指标叫回流率,是指上个月有多少不活跃/本月消费用户活跃/消费。因为不活跃的用户总数几乎不变,这里的回流率也差不多。

活跃用户的下降趋势更为明显,占3%~5%。这里的活跃用户可以被视为连续消费用户,质量在一定程度上高于回流用户。

结合回流用户和活跃用户,在后期消费用户中,60%是回流用户,40%是活跃用户/连续消费用户。整体质量还不错,但这两个层次还有改进的空间,数据可以继续细化。

接下来,我们将分析用户的质量,因为消费行为有明显的28种倾向,我们需要知道高质量的用户为消费做出了多少贡献。

根据用户的消费金额,新建一个对象。cumsum,它是累加函数。累计金额逐行计算,最后2500315为总消费。

转换成百分比。

绘制趋势图,横坐标按贡献金额排序,纵坐标为用户累计贡献。很明显,前2万用户贡献了40%的消费。后4000名用户贡献了60%,确实呈现出28种趋势。

统计销量,前2万用户贡献45%的销量,高消费用户贡献55%的销量。在消费领域,密切关注优质用户是永恒的事实。

接下来,计算用户的生命周期,将第一次消费定义为整个用户的生命。

统计用户第一次消费和最后一次消费的时间,减少每个用户的生命周期。由于数据中的用户是前三个月的第一次消费,这里的生命周期代表了1月至3月的生命周期。理论上,随着后续消费,用户的平均生命周期将会增加。

求一下平均,所有用户的平均生命周期是134天,比预想的高,但是平均数不靠谱,还是看一下分布吧,大家有兴趣可以用describe,更详细。

因为这里的数据类型是timedelta时间,它不能直接制作直方图,所以先转换成值。直接去除转换的方式timedelta这里的函数就够了np.timedelta ** (1,'D'),D表示天,1表示1天,作为单位使用。** x-min已经说是天了,两者相除是周期天数。

看,大多数用户只消费一次,大部分生命周期都集中在0天。但这不是我们想要的答案。我们不妨排除只消费一次的新客户,计算所有消费两次以上的老客户的生命周期。

转换成DataFrame。

筛选出lifetime>0,也就是说,那些只消费过一次的人。制作直方图。

这张照片比上面可靠得多,尽管许多用户的生命周期仍然接近0天。这是双峰趋势图。一些质量差的用户,虽然消费了两次,但仍然不可持续,应该在用户第一次消费后30天内进行指导。少数用户集中在50~300天,属于普通生命周期、高质量用户生命周期、集合中在400天以后,这已经属于忠诚用户了,大家有兴趣可以跑一下400天+的用户占老客比多少,占总量多少。

消费两次以上的用户生命周期是276天,远高于总体。从策略看,用户首次消费后应该花费更多的引导其进行多次消费,提供生命周期,这会带来2.5倍的增量。

再来计算留存率,留存率也是消费分析领域的经典应用。它指用户在第一次消费后,有多少比率进行第二次消费。和回流率的区别是留存倾向于计算第一次消费,并且有多个时间窗口。

这里用到merge函数,它和SQL中的join差不多,用来将两个DataFrame进行合并。我们选择了inner 的方式,对标inner join。即只合并能对应得上的数据。这里以on=user_id为对应标准。这里merge的目的是将用户消费行为和第一次消费时间对应上,形成一个新的DataFrame。suffxes参数是如果合并的内容中有重名column,加上后缀。除了merge,还有join,concat,用户接近,查看文档即可。

这里将order_date和order_date_min相减。获得一个新的列,为用户每一次消费距第一次消费的时间差值。

日期转换成时间。

将时间差值分桶。我这里分成0~3天内,3~7天内,7~15天等,代表用户当前消费时间距第一次消费属于哪个时间段呢。这里date_diff=0并没有被划分入0~3天,因为计算的是留存率,如果用户仅消费了一次,留存率应该是0。另外一方面,如果用户第一天内消费了多次,但是往后没有消费,也算作留存率0。

用pivot_table数据透视,获得的结果是用户在第一次消费之后,在后续各时间段内的消费总额。

计算一下用户在后续各时间段的平均消费额,这里只统计有消费的平均值。虽然后面时间段的金额高,但是它的时间范围也宽广。从平均效果看,用户第一次消费后的0~3天内,更可能消费更多。

但消费更多是一个相对的概念,我们还要看整体中有多少用户在0~3天消费。

依旧将数据转换成是否,1代表在该时间段内有后续消费,0代表没有。

只有2.5%的用户在第一次消费的次日至3天内有过消费,3%的用户在3~7天内有过消费。数字并不好看,CD购买确实不是高频消费行为。时间范围放宽后数字好看了不少,有20%的用户在第一次消费后的三个月到半年之间有过购买,27%的用户在半年后至1年内有过购买。从运营角度看,CD机营销在教育新用户的同时,应该注重用户忠诚度的培养,放长线掉大鱼,在一定时间内召回用户购买。

怎么算放长线掉大鱼呢?我们计算出用户的平均购买周期。

我们将用户分组,groupby分组后的数据,也是能用for进行循环和迭代的。第一个循环对象user,是分组的对象,即user_id;第二个循环对象group,是分组聚合后的结果。为了举例我用了print,它依次输出了user_id=1,user_id=2时的用户消费数据,是一组切割后的DataFrame。

大家应该了解分组循环的用法,但是网不建议大家用for循环,它的效率非常慢。要计算用户的消费间隔,确实需要用户分组,但是用apply效率更快。

定义一个计算间隔的函数diff,输入的是group,通过上面的演示,大家也应该知道分组后的数据依旧是DataFrame。我们将用户上下两次消费时间相减将能求出消费间隔了。shift函数是一个偏移函数,和excel上的offset差不多。

x.shift()是往上偏移一个位置,x.shift(-1)是往下偏移一个位置,加参数axis=1则是左右偏移。当我想将求用户下一次距本次消费的时间间隔,用shift(-1)减当前值即可。案例用的diff函数便借助shift方法,巧妙的求出了每位用户的两次消费间隔,若为NaN,则没有下一次。

然后就简单了,用mean函数即可求出用户的平均消费间隔时间是68天。想要召回用户,在60天左右的消费间隔是比较好的。

看一下直方图,典型的长尾分布,大部分用户的消费间隔确实比较短。不妨将时间召回点设为消费后立即赠送优惠券,消费后10天询问用户CD怎么样,消费后30天提醒优惠券到期,消费后60天短信推送。这便是数据的应用了。

假若大家有兴趣,不妨多做几个分析假设,看能不能用Python挖掘出更有意思的数据,1月、2月、3月的新用户在留存率有没有差异?不同生命周期的用户,他们的消费累加图是什么样的?消费留存,划分其他时间段怎么样?

你若想要追求更好的Python技术,可以把上述的分析过程都封装成函数。当下次想要再次分析的时候,怎么样只用几个函数就搞定,而不是继续重复码代码。

这里的数据只是用户ID,消费时间,购买量和消费金额。如果换成用户ID,浏览时间,浏览量,能不能直接套用?浏览变成评论、点赞又行不行?消费行为变成用户其他行为呢?我可以明确地告诉你,大部分代码只要替换部分就能直接用了。把所有的结果分析出来需要花费多少时间呢?

Python的优势就在于快速和灵活,远比Excel和SQL快。这次是CD网站的消费行为,下次换成电商,换成O2O,一样可以在几分钟内计算出用户生命周期,用户购买频次,留存率复购率回购率等等。这对你的效率提升有多大帮助?

经过一系列的讲解,你是否掌握了Python的数据分析姿势?这里的很多技巧,都和我以前的文章相关,有excel的函数影子,有数据可视化的用法,有分析思路,有描述统计的知识,有各种业务指标,有接近SQL的数据规整,虽然是Python进行数据分析,也是整个数据分析的总结。

所以,所有的课程都结束啦。七周成为数据分析师,告一段落。

——————

因为知乎关闭了外链,数据可以去我的公众号(ID:tracykanc),后台发送「CD数据」获得地址。欢迎关注。

扫码免费用

源码支持二开

申请免费使用

在线咨询