在互联网行业中,电子商务领域绝对是数据分析用途最多的地方,各大电商平台都依赖数据分析帮助其挖掘用户订单增长机会。比如某宝的随手买一件,核心思路也就是根据用户的日常浏览内容及停留时间,以及订单的关联度来进行推荐的。
本篇文章,我们来通过一个真实的电商数据集进行分析,在复习前面内容的基础上,也可以感受一下电商数据分析的分析流程。
最近某个电商网站需要策划一场推广活动,通过发短信的方式,向客户发送广告和优惠信息,吸引他们来购物。但由于预算及短信限制,无法对全量客户发送,需要找出最有可能转化的人群,定向发送推广信息,同时,下单的行为往往也跟时间呈现一定的关联关系,推送时间也需要考虑。
基于以上的需求说明,作为数据分析师,我们就需要根据需求,制定自己的分析计划。那么我们的任务就是:
任务明确之后,就需要考虑我们要完成以上任务,需要哪些数据支撑,开始找数据部门提供相应的数据支持。
通过一顿友(唇)好(枪)协(舌)商(战),最终从数据部门要到如下数据:
拿到数据之后,我们就可以大展拳脚了。
为了方便我们学习,需要自己模拟一些相关数据,不想模拟的话,可以在公众号联系获取。
拿到数据后,解压后可以看到如下几个文件:
我们先来看一下各个表的字段说明:
user_behavior_time_resampled.csv vip_users.csv
从这里开始,我们就开始使用我们前面了解的一些包和库来读取数据了,这里首先是使用pandas来加载数据。
import pandas as pd
df_user_log = pd.read_csv("EComm/user_behavior_time_resampled.csv")
df_vip_user = pd.read_csv("EComm/vip_user.csv")
df_user_info = pd.read_csv("EComm/user_info.csv")
df_user_log
df_vip_user
df_user_info
加载完后,输出如下:
❝这里,df_user_log表中有一个 time_stamp 和 timestamp 字段,我们需要了解一下这两个字段的意思。
先看一下这两个字段的边界值
time_stamp_max = str(df_user_log['time_stamp'].max())
time_stamp_min = str(df_user_log['time_stamp'].min())
print("time_stamp max: " + time_stamp_max, "time_stamp min: " + time_stamp_min)
timestamp_max = str(df_user_log['timestamp'].max())
timestamp_min = str(df_user_log['timestamp'].min())
print("timestamp max: " + timestamp_max, "timestamp min: " + timestamp_min)
输出如下:
time_stamp max: 1112, time_stamp min: 511
timestamp max: 86399.99327792758, timestamp min: 0.10787397733480476
可以看到,time_stamp 的最大值为 1112,最小值为 511,而 timestamp 的最大值为 86399.99 最小值为 0.1。
从数据集的描述中,用户行为表是用户 6 个月的行为,那 time_stamp 最大 1112,最小 511 看起来就特别像日期。代表最小日期是 5 月 11 日,最大日期是 11 月 12 日。
那既然 time_stamp 是日期,那 timestamp 会不会是具体的时间呢?timestamp 的最大值为 86399 ,而一天最大的秒数为 24*3600 = 86400。两个数字非常接近,那基本可以认定 timestamp 代表的是一天中的第几秒发生了这个行为。
破解了两个时间字段的问题,为了避免后面有歧义,我们将 time_stamp 列重命名为 date。
df_user_log.rename(columns={'time_stamp':'date'}, inplace = True)
df_user_log
完成数据读取,了解了各个字段的含义之后,我们就可以开始进行数据清洗了。
针对数据分析中使用的数据集,我们需要尽可能去了解数据的完整性,与我们数据分析无关的字段,不清洗也没关系。但是,重点的分析维度,如果出现缺失,我们就要考虑是否进行补全或者是直接去除。
我们先来看下缺失值情况:
df_user_log.isnull().sum()
输出如下:
user_id 0
item_id 0
cat_id 0
seller_id 0
brand_id 18132
date 0
action_type 0
timestamp 0
dtype: int64
从上面的结果来看,log表有18000多数据缺少品牌数据,缺失率比较低0.16%(1.8w/1098w),一般这个数量级不会影响到数据分析的整体严谨性,我们暂不做处理。
df_user_info.isnull().sum()
输出如下:
user_id 0
age_range 2217
gender 6436
dtype: int64
从结果中可以看出,info表中有2217条数据缺失年龄数据,6436条数据缺失性别字段。但是我们是有对用户的年龄和性别做分析的,而且补全的话也是完全没规律补全的,所以这里我们就直接删除。
df_user_info = df_user_info.dropna()
df_user_info
df_vip_user.isnull().sum()
输出:
user_id 0
merchant_id 0
label 0
dtype: int64
从结果来看,vip表无缺失,不需要处理。
做完以上的准备工作,就要开始进入我们最核心的数据分析工作了。
还记得我们的分析任务吗? 第一是要定位需要推广的人群,第二是确定推广信息发送的时间。那么针对我们的两个任务,来进行接下来的工作。
我们先通过DataFrame的value_counts函数来看一下年龄的分布情况:
df_user_info.age_range.value_counts()
输出:
3.0 110952
0.0 90638
4.0 79649
2.0 52420
5.0 40601
6.0 35257
7.0 6924
8.0 1243
1.0 24
Name: age_range, dtype: int64
除开未知的数据我们不看,可以发现,取值为3和4的是占比最大的。3和4又分别代表25-30岁和30-34岁。我们再用代码计算出25-34岁的用户比例。
user_ages = df_user_info.loc[df_user_info["age_range"] != 0, "age_range"]
user_ages.loc[(user_ages == 3) | (user_ages == 4) ].shape[0] / user_ages.shape[0]
输出:
0.5827529275078729
可以看出,25-34岁区间的用户比例在58%。
##(2)用户性别分析 接下来,我们再用value_counts函数来分析性别。
df_user_info.gender.value_counts()
输出:
0.0 285634
1.0 121655
2.0 10419
Name: gender, dtype: int64
从字段含义来看,0代表女性,1代表男性,2代表未知。由此可以得出,平台的核心用户群体是女性,数量是男性的2.35倍。
截止到这里,我们通过用户群体的分析,已经可以得出:平台的核心用户是25-34岁的女性,但这样情况是否符合实际呢?毕竟我们只是分析了注册用户信息,并没有与订单数据结合来分析。说不定只是女性注册的多,但下单的少。所以下一步,我们将用户信息和订单数据来结合起来验证一下猜想是否合理。
上面聊到了,我们需要将用户信息和订单信息结合起来分析是否是女性的购买力更强。但是用户数据和订单数据属于在不用的表中,那我们该怎么处理呢? 可以看一下数据情况,发现用户表和订单表都有一个叫user_id的字段,这样,我们就有办法把两张表关联起来了。
通过user_id将两个表关联起来:
df_user_log = df_user_log.join(df_user_info.set_index('user_id'), on = 'user_id')
df_user_log
输出:
由上面的输出可以看到,用户表的年龄和性别就被合并到订单表了。接下来我们就可以根据下单用户来分析用户的性别和年龄了。
df_user_log.loc[df_user_log["action_type"] == "order", ["age_range"]].age_range.value_counts()
输出:
3.0 172525
4.0 153795
0.0 114908
5.0 79298
6.0 61534
2.0 59072
7.0 10785
8.0 1924
1.0 21
Name: age_range, dtype: int64
通过上述结果,可以看出,下单的年龄段和用户信息的分析基本一致,25-34岁的人占比59.9%。
df_user_log.loc[df_user_log["action_type"] == "order", ["gender"]].gender.value_counts()
输出:
0.0 467381
1.0 161999
2.0 24482
Name: gender, dtype: int64
通过上述结果可以看出,依然是女性的下单量更大。到这里,我们基本可以下结论:我们发送推广短信的群体为25-34岁的女性用户。
到这里,我们的任务基本完成了一半了,已经确定好了发送短信的群体。但是另外一个任务是确定发送时间。我们接着往下分析。
这里我们通过对各个日期分组,查看哪个时间段下单的人群最多。因为数据是近6个月的数据,那我们就把数据分为6个组,来看一下:
df_user_log.loc[df_user_log["action_type"] == "order", ["date"]].date.value_counts(bins = 6)
输出:
(1011.0, 1111.0] 333721
(811.0, 911.0] 70699
(911.0, 1011.0] 69427
(510.399, 611.0] 68776
(611.0, 711.0] 62901
(711.0, 811.0] 54053
Name: date, dtype: int64
可以看出,在10月11日到11月11日下单的数量最多。分析完日期,我们再来看一下哪个时间段下单的比较多。
timestamp 字段存储了每条记录下单的时间,从当天零点开始累积的秒数。并不是很直观,我们更希望可以基于小时级的数据去分析。所以我们考虑基于 timestamp 这一列,新创建一列时间,来表示小时。
df_user_log.loc["time_hours_view"] = df_user_log["timestamp"]/3600
df_user_log
输出:
我们直接用 value_count 来统计新增的 time_hours_view 字段,就可以实现对一天中的小时级分布进行分布统计。我们以两个小时为尺度,来查看分布,所以分为 12 组。
df_user_log.loc[df_user_log["action_type"] == "order", ["time_hours_view"]].time_hours_view.value_counts(bins = 12)
输出:
(20.0, 22.0] 94209
(22.0, 24.0] 91529
(18.0, 20.0] 91330
(16.0, 18.0] 85681
(14.0, 16.0] 75372
(12.0, 14.0] 63580
(10.0, 12.0] 50909
(8.0, 10.0] 38938
(6.0, 8.0] 27962
(4.0, 6.0] 19428
(2.0, 4.0] 12639
(-0.025, 2.0] 8000
Name: time_hours_view, dtype: int64
从上述结果可以看出,晚上八点到十点是下单最多的。
到这里,我们根据需求进行数据分析的任务就已经全部完成了。已经基本确定,推广短信发送群体为:25-34岁的女性用户,发送短信的最佳时间周期是10月下旬到11月中旬的晚上八点到十点。
❝欢迎关注公众号:服务端技术精选
❝如果有疑问或者是其他需求,可公众号留言