前文已经对数据分析的流程作了较为宏观的总结,现在我们就结合具体地电商网站的行为数据来对用户行为做一个简单的分析。主要完成一个数据的一些统计与可视化。
1.1 电商网站行为分析
1、需求:
- 用户的购物行为情况;
- 统计每天各行为的访问次数,并以折线图显示;
- 找出购买率最高的前二十个商品品类,并以柱状图展示;
2、数据集介绍:
数据集包含了2017年11月25日至2017年12月3日之间,有行为的约一百万随机用户的所有行为(行为包括点
击、购买、加购、喜欢),数据集的每一行表示一条用户行为,由用户ID、商品ID、商品类目ID、行为类型和
时间戳组成,并以逗号分隔;用户行为类型共有四种,它们分别是:
- pv:商品详情页点击;
- buy:购买;
- cart:加入购物车;
- fav:收藏商品;
3、需求的实现过程:
分析数据 —> 整理并清除异常数据 —> 实现需求
1、分析数据
数据有3个多G,全部读取耗费时间与内存,因此使用pandas的迭代读取方法,先获取前一万条数据,熟悉数
据内容,并加入列名
import pandas as pd
%matplotlib inline
user_behavior = pd.read_csv('UserBehavior.csv',header=None,iterator=True)
head_data = user_behavior.get_chunk(10000)
head_data.head()
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
0 | 1 | 2268318 | 2520377 | pv | 1511544070 |
1 | 1 | 2333346 | 2520771 | pv | 1511561733 |
2 | 1 | 2576651 | 149192 | pv | 1511572885 |
3 | 1 | 3830808 | 4181361 | pv | 1511593493 |
4 | 1 | 4365585 | 2520377 | pv | 1511596146 |
2、对数据进行整理、清洗
2.1、添加列名,数据特征分别是:用户ID,商品ID,商品类目ID,行为类型,时间戳
head_data.columns = ['user_id','goods_id','category_id','behaviour','timestamp']
2.2、查看是否有缺失值,有两种方法:
两种方式对比:
当数据集较大时,推荐使用第一种方式,虽然有些麻烦,但是节省时间和空间,size是一个对象的属性,调用
时获取值的时间复杂度是O(1);
第二种方式会将所有的数据过滤一遍进行判断,很慢,而且占用内存较大
可以看出以上数据没有缺失值,不需要进行缺失值的处理
# 1 对比每一列数据的大小
print(head_data['user_id'].size)
print(head_data['goods_id'].size)
print(head_data['category_id'].size)
print(head_data['behaviour'].size)
print(head_data['timestamp'].size)
10000
10000
10000
10000
10000
# 2 直接用pandas提供的接口
head_data.isnull().any()
user_id False
goods_id False
category_id False
behaviour False
timestamp False
dtype: bool
2.3、将时间戳转为时间格式,并新加一列time
head_data['time'] = pd.to_datetime(head_data['timestamp'],unit='s')
2.4、时间戳这列数据下面不会用到,可以删除掉
head_data = head_data.drop(['timestamp'],axis=1)
2.5、将time字段设为索引,目的是为了方便清除异常时间的数据
head_data.set_index('time',inplace=True)
2.6、数据是2017年11月25日至2017年12月3日之间,将异常时间的数据清洗掉
head_data = head_data['2017-11-25':'2017-12-3']
3、数据整理完,开始解决需求
3.1、需求1 : 统计用户的每个购物行为,思路:使用groupby进行分组并统计
count_by_user_behav = head_data.groupby(['user_id','behaviour']).count()
count_by_user_behav.head()
goods_id | category_id | ||
---|---|---|---|
user_id | behaviour | ||
1 | pv | 53 | 53 |
100 | buy | 8 | 8 |
fav | 3 | 3 | |
pv | 72 | 72 | |
1000 | cart | 1 | 1 |
# 只取一列的次数,作为画图是的Y轴的值就可以了
count_by_user_behav = count_by_user_behav['goods_id']
count_by_user_behav.head()
user_id behaviour
1 pv 53
100 buy 8
fav 3
pv 72
1000 cart 1
Name: goods_id, dtype: int64
# 使用pandas自带的画图功能,因为用户很多,所以x轴就很长,双击图片可以放大
count_by_user_behav.plot(kind='bar', figsize=(150, 10))
<matplotlib.axes._subplots.AxesSubplot at 0x276d42a0d30>
3.2、需求2 : 统计每天各行为的访问次数,并以折线图显示
# 接下来结合matplotlib画图
from matplotlib import pyplot as plt
%matplotlib inline
# 设置画布尺寸
plt.figure(figsize=(20, 8))
# 以行为类型进行分组
for group_name,group_data in head_data.groupby('behaviour'):
# 对每天的行为进行统计,resample中的D表示天,也可以用H按小时统计
count_by_day = group_data.resample('D').count()['behaviour']
# 以日期作为X轴,以次数为y轴
x = count_by_day.index
y = count_by_day.values
# 设置x,y轴数据以及每条线的标签名
plt.plot(range(len(x)), y, label=group_name)
# 设置x轴的刻标以及对应的标签,rotation是设置标签的倾斜度
plt.xticks(range(len(x)), x, rotation=45)
# 对每条折线的含义进行标注,自动选择最佳位置
plt.legend(loc='best')
plt.show()
可以清晰看出四种购物行为的走势图
3.3需求3 : 找出购买率最高的前二十个商品品类,并以柱状图展示
思路:按商品种类进行分组,购买率 = 购买次数/(访问+购物车+收藏+购买)
# 取消以时间为索引
head_data = head_data.reset_index()
# 按商品种类进行分组
count_by_category_id = head_data.groupby('category_id')
# 分组后每组数据的数量
count_by_category_id.size()
category_id
8254 2
16219 5
22129 1
35290 16
48094 1
50601 4
58498 1
64179 2
65362 9
68149 1
72526 5
84264 5
101859 1
102272 28
107693 1
113102 5
119741 29
136225 1
144028 3
146830 10
149192 89
149656 1
151648 2
152639 1
154040 94
155172 1
160181 6
163196 1
167871 2
171529 11
..
4897718 1
4901188 1
4911958 1
4915680 2
4918438 15
4919077 5
4921617 8
4936889 4
4958794 9
4962280 9
4974254 1
4978351 1
4981793 1
4988053 1
4993094 41
5008466 3
5012555 1
5018044 1
5028097 2
5030562 1
5045733 1
5046132 2
5048062 1
5052177 1
5053508 4
5071267 16
5091223 2
5103246 1
5140516 1
5150761 1
Length: 942, dtype: int64
length的意思是在这一万条数据中,出现了942个商品种类
# 看一下分组后的部分数据
for group_name,group_data in count_by_category_id:
print('组名:',group_name)
print('数据:')
print(group_data)
print(group_data.shape)
break
组名: 8254
数据:
time user_id goods_id category_id behaviour
7109 2017-11-25 01:18:30 1000326 4367195 8254 pv
7114 2017-11-25 02:55:26 1000326 4367195 8254 pv
(2, 5)
思路:通过shape看出这组数据的形状为两行五列,因此可以直接用shape[0]作为购物的总次数使用,接下来
再以behaviour分组,通过size属性,获取buy这一组的次数,最后将商品种类与购买率一一对应保存在字典中,使用内置函数sorted对字典进行排序
con_dict = {}
for group_name,group_data in count_by_category_id:
# 总次数
total = group_data.shape[0]
buy = 0
try:
#有些商品没有购买行为,以buy作为索引获取时会出错,使用异常语句捕捉一下
buy = group_data.groupby('behaviour').size()['buy']
except:
pass
# 转化率
convention = buy/total*100
# 类别名称对应转化率
con_dict[group_name] = convention
# 排序
sort_con = sorted(con_dict.items(),key=lambda item:item[1],reverse=True)
# 对排好序的列表取值
sort_con_20 = sort_con[:20]
sort_con_20
[(895939, 100.0),
(1597811, 100.0),
(1833532, 100.0),
(2550060, 100.0),
(2895013, 100.0),
(2951233, 100.0),
(2975713, 100.0),
(4238377, 100.0),
(4242742, 100.0),
(4470576, 100.0),
(4718844, 100.0),
(890050, 60.0),
(835895, 55.55555555555556),
(512076, 50.0),
(1879672, 50.0),
(3025028, 50.0),
(3445085, 50.0),
(3695050, 50.0),
(3797203, 50.0),
(1601543, 40.0)]
sorted的用法: 第一个参数是进行排序的可迭代对象; key:主要是用来比较的元素,lambda函数的参数取自要排序的可迭代对象,指定可迭代对象中的元素进行排序; reverse:排序规则,默认升序,True表示降序;
前二十个商品种类及对应购买率如下,拿到这个,就可以使用matplotlib进行绘图了
# 获取所有的商品种类
tick_label = [i[0] for i in sort_con_20]
# 获取转化率
num_list = [i[1] for i in sort_con_20]
# 开始画图
plt.figure(figsize=(20, 8))
plt.bar(range(len(sort_con_20)), num_list,tick_label=tick_label)
plt.show()