在电商的推荐系统中,常用到关联分析。
比如上图中,通过关联分析,Louis 和 Alice 有着类似的购物行为,那么在 Louis 购物的时候,推荐系统就可能会推荐他购买电脑。
假如,现在有一组数据,每一行代表每一个人对一组商品 [ 课程1,课程2,电子书1,电子书2 ] 的购买行为,1代表买了,0代表没买。
基于这组数据,可以算出用户同时购买两本电子书的百分比,基于这个百分比,推荐系统就可以在用户本来只打算买一本书的时候,推荐给他捆绑销售的策略。
下面来求解顾客同时购买2本电子书的百分比。
import numpy as np
## Data : row is customer shopping basket
## row = [course1, course2, ebook1, ebook2]
## value 1 indicates that an item was bought
basket = np.array([[0,1,1,0],
[0,0,0,1],
[1,1,0,0],
[0,1,1,1],
[1,1,1,0],
[0,1,1,0],
[1,1,0,1],
[1,1,1,1]])
## One-liner
copurchases = np.sum(np.all(basket[:,2:],axis=1))/ basket.shape[0]
## 输出结果
print(copurchases)
## 0.25
作者这里给出的「一行」代码:
copurchases = np.sum(np.all(basket[:,2:],axis=1))/ basket.shape[0]
下面来拆解一下:
Step 1
由于只要求同时购买两本书的情况,切片的时候,则要切出所有行的后两列。
在Numpy的二维数组切片中,basket[ : , 2: ]
逗号前,对行进行切片,只有冒号,即没有指定开始和结尾,代表所有的行。
逗号后,对列进行切片,从下标为2的第三列开始切片
切片结果如下:
basket[:,2:]
## 结果如下:
[[1 0]
[0 1]
[0 0]
[1 1]
[1 0]
[1 0]
[0 1]
[1 1]]
注:一个完整的切片有两个冒号:
开始索引:结束索引:步长
如果第二个冒号省略,则代表按照正向顺序进行切片步长为1。
Step 2
通过 np.all() 对切片后的数组进行计算,如果两个元素都是1,则返回布尔值Ture,由于这里是要考察每一个人是否两本电子书都买了,则需要加上轴参数,axis=1,按照每一行进行统计。
看结果:
print(np.all(basket[:,2:],axis=1))
## 结果:
[False False False True False False False True]
得到 2 个True , 6 个False
Step 3
将上面的布尔数组,通过np.sum() 进行累加计算,为Ture的只有2个,结果如下:
print(np.sum((np.all(basket[:,2:],axis=1))))
## 结果
2
注:在Python中对布尔值进行运算时,True为1,False为0
Step 4
现在有了两个都买的人数,要求百分比,还要知道人的总数,即总行数。
在Numpy中,shape返回多维数组的长度,比如一个2*3的二维数组,则返回(2,3),可以通过以下两种写法:
## 调用 numpy的shape()方法,入参为数组
np.shape(basket)
## 调用数组的shape属性,这里没有括号哦
basket.shape
## 结果都为:(8, 4) 代表,8行4列
## 那么求总行数,则为:
np.shape(basket)[0]
basket.shape[0]
## 结果为:8
Step 5
所以,求百分比的最终结果是:2/8 = 0.25
np.sum(np.all(basket[:,2:],axis=1))/ basket.shape[0]
## 结果为:0.25
知识点回顾及参考资料
slice 切片
np.sum() 求和
np.all()
https://www.xz577.com/j/196.html
np.shape() 或 .shape
https://www.jianshu.com/p/e083512e4f4c
图片来源:《Python One-Liners》书中图例 Figure 3-4