一、引言

购物篮分析是商业领域最前沿、最具挑战性的问题之一,也是许多企业重点研究的问题。购物篮分析是通过发现顾客在一次购买行为中放入购物篮中不同商品之间的关联,研究顾客的购买行为,从而辅助零售企业制定营销策略的一种数据分析方法。
       本篇文章使用 Apriori 关联规则算法实现购物篮分析,发现超市不同商品之间的关联关系,并根据商品之间的关联规则制定销售策略。

二、数据探索分析

2.1 查看数据特征

搜索数据的特征,查看每列属性、最大值、最小值、是了解数据的第一步。

import numpy as np
import pandas as pdinputfile = './data/GoodsOrder.csv'   # 输入的数据文件
data = pd.read_csv(inputfile,encoding = 'gbk')  # 读取数据
data .info()  # 查看数据属性data = data['id']
description = [data.count(),data.min(), data.max()]  # 依次计算总数、最小值、最大值
description = pd.DataFrame(description, index = ['Count','Min', 'Max']).T  # 将结果存入数据框
print('描述性统计结果:\n',np.round(description))  # 输出结果

结果如下

可到每列属性共有43367个观测值,并不存在缺失值。“id”属性的最大值和最小值,可得某商品零售企业共收集9835个购物篮数据,其中包含169个不同的商品类别,售出商品总数43367件。

2.2 分析热销商品

热销情况分析可以助力商品优选。计算销量排名前10的商品销量及占比,并绘制条形图显示销量前10的商品销量情况。

# 销量排行前10商品的销量及其占比
import pandas as pd
inputfile = './data/GoodsOrder.csv'  # 输入的数据文件
data = pd.read_csv(inputfile,encoding = 'gbk')  # 读取数据
group = data.groupby(['Goods']).count().reset_index()  # 对商品进行分类汇总
sorted=group.sort_values('id',ascending=False)
print('销量排行前10商品的销量:\n', sorted[:10])  # 排序并查看前10位热销商品# 画条形图展示出销量排行前10商品的销量
import matplotlib.pyplot as plt
x=sorted[:10]['Goods']
y=sorted[:10]['id']
plt.figure(figsize = (8, 4))  # 设置画布大小
plt.barh(x,y)
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.xlabel('销量')  # 设置x轴标题
plt.ylabel('商品类别')  # 设置y轴标题
plt.title('商品的销量TOP10(3001)')  # 设置标题
plt.savefig('./data//top10.png')  # 把图片以.png格式保存
plt.show()  # 展示图片# 销量排行前10商品的销量占比
data_nums = data.shape[0]
for idnex, row in sorted[:10].iterrows():print(row['Goods'],row['id'],row['id']/data_nums)

结果如下

通过分析热销商品的结果可知,全脂牛奶的销量最高,为2513件,占比5.795%;其次是其他蔬菜、面包卷和苏打,占比分别为4.388%、4.171%、3.955%。

2.3 分析商品结构

对每一类商品的热销程度进行分析,有利于商品制定商品在货架上的摆放策略和位置。分析归类后各类别商品的销量及其占比后,绘制饼图显示各类商品的销量占比情况

import pandas as pd
inputfile1 = './data/GoodsOrder.csv'
inputfile2 = './data/GoodsTypes.csv'
data = pd.read_csv(inputfile1,encoding = 'gbk')
types = pd.read_csv(inputfile2,encoding = 'gbk')  # 读入数据group = data.groupby(['Goods']).count().reset_index()
sort = group.sort_values('id',ascending = False).reset_index()
data_nums = data.shape[0]  # 总量
del sort['index']sort_links = pd.merge(sort,types)  # 合并两个datafreame 根据type
# 根据类别求和,每个商品类别的总量,并排序
sort_link = sort_links.groupby(['Types']).sum().reset_index()
sort_link = sort_link.sort_values('id',ascending = False).reset_index()
del sort_link['index']  # 删除“index”列# 求百分比,然后更换列名,最后输出到文件
sort_link['count'] = sort_link.apply(lambda line: line['id']/data_nums,axis=1)
sort_link.rename(columns = {'count':'percent'},inplace = True)
print('各类别商品的销量及其占比:\n',sort_link)
outfile1 = './data/percent.csv'
sort_link.to_csv(outfile1,index = False,header = True,encoding='gbk')  # 保存结果# 画饼图展示每类商品销量占比
import matplotlib.pyplot as plt
data = sort_link['percent']
labels = sort_link['Types']
plt.figure(figsize=(8, 6))  # 设置画布大小
plt.pie(data,labels=labels,autopct='%1.2f%%')
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.title('每类商品销量占比(3001)')  # 设置标题
plt.savefig('./data/persent.png')  # 把图片以.png格式保存
plt.show()

结果如下

 

通过分析各类别商品的销量及其占比情况可知,非酒精饮料、西点、果蔬3类商品的销量差距不大,占比总销量的50%左右

进一步查看销量第一的非酒精饮料类商品和销量第二的西点的内部结构,并绘制饼图显示其销量占比情况

# 筛选“非酒精饮料”类型的商品,然后求百分比。
alcohol = sort_links.loc[sort_links['Types'] == '非酒精饮料']  # 挑选商品类别为“非酒精饮料”并排序
child_nums = alcohol['id'].sum()  # 对所有的“非酒精饮料”求和
alcohol['child_percent'] = alcohol.apply(lambda line: line['id']/child_nums,axis = 1)  # 求百分比
alcohol.rename(columns = {'id':'count'},inplace = True)
print('非酒精饮料内部商品的销量及其占比:\n',alcohol)
# 筛选“西点”类型的商品,然后求百分比。
desserts = sort_links.loc[sort_links['Types'] == '西点']  # 挑选商品类别为“西点”并排序
child_nums = desserts['id'].sum()  # 对所有的“西点”求和
desserts['child_percent'] = desserts.apply(lambda line: line['id']/child_nums,axis = 1)  # 求百分比
desserts.rename(columns = {'id':'count'},inplace = True)
print('西点内部商品的销量及其占比:\n',desserts)# 画饼图展示非酒精饮品内部各商品的销量占比
import matplotlib.pyplot as plt
data = alcohol['child_percent']
labels = alcohol['Goods']
plt.figure(figsize = (8,6))  # 设置画布大小
explode = (0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.08,0.3,0.1,0.3)  # 设置每一块分割出的间隙大小
plt.pie(data,explode = explode,labels = labels,autopct = '%1.2f%%',pctdistance = 1.1,labeldistance = 1.2)
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.title("非酒精饮料内部各商品的销量占比(3001)")  # 设置标题
plt.axis('equal')
plt.show()  # 展示图形
# 画饼图展示西点内部各商品的销量占比
data = desserts['child_percent']
labels = desserts['Goods']
plt.figure(figsize = (8,6))  # 设置画布大小
plt.pie(data,explode = None ,labels = labels,autopct = '%1.2f%%',pctdistance = 1.1,labeldistance = 1.2)
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.title("西点内部各商品的销量占比(3001)")  # 设置标题
plt.axis('equal')
plt.show()  # 展示图形

结果如下

 

 

通过分析非酒精饮料内部商品的销量及其情况可知,全脂牛奶的销量在非酒精饮料的总销量中占比超过33%,前3种非酒精饮料的销量在非酒精饮料的总销量中的占比接近70%。

同理分析西点内部商品的销量及其情况可知,面包卷的销量在西点的总销量中占比超过25%,其次是糕点,占比12.17%

三、数据预处理

3.1 数据转换

通过对数据探索分析发现数据完整,并不存在缺失值。建模之前需要转变数据的格式,才能使用Apriori函数进行关联分析

import pandas as pd
inputfile='./data/GoodsOrder.csv'
data = pd.read_csv(inputfile,encoding = 'gbk')# 根据id对“Goods”列合并,并使用“,”将各商品隔开
data['Goods'] = data['Goods'].apply(lambda x:','+x)
data = data.groupby('id').sum().reset_index()# 对合并的商品列转换数据格式
data['Goods'] = data['Goods'].apply(lambda x :[x[1:]])
data_list = list(data['Goods'])# 分割商品名为每个元素
data_translation = []
for i in data_list:p = i[0].split(',')data_translation.append(p)
print('数据转换结果的前5个元素:\n', data_translation[0:5])

结果如下

四、模型构建

4.1商品购物篮关联规则模型构建

建模流程如图:

模型主要由输入、算法处理、输出3个部分组成。输入部分包括建模样本数据的输入和建模参数的输入。算法处理部分是采用 Apriori 关联规则算法进行处理。输出部分为采用 Apriori 关联规则算法进行处理后的结果。
       模型具体实现步骤:首先设置建模参数最小支持度、最小置信度,输入建模样本数据;然后采用 Apriori 关联规则算法对建模的样本数据进行分析,以模型参数设置的最小支持度、最小置信度以及分析目标作为条件,如果所有的规则都不满足条件,则需要重新调整模型参数,否则输出关联规则结果。
       目前,如何设置最小支持度与最小置信度并没有统一的标准。大部分都是根据业务经验设置初始值,然后经过多次调整,获取与业务相符的关联规则结果。本案例经过多次调整并结合实际业务分析,选取模型的输入参数为:最小支持度0.02、最小置信度0.35。

from numpy import *def loadDataSet():return [['a', 'c', 'e'], ['b', 'd'], ['b', 'c'], ['a', 'b', 'c', 'd'], ['a', 'b'], ['b', 'c'], ['a', 'b'],['a', 'b', 'c', 'e'], ['a', 'b', 'c'], ['a', 'c', 'e']]def createC1(dataSet):C1 = []for transaction in dataSet:for item in transaction:if not [item] in C1:C1.append([item])C1.sort()# 映射为frozenset唯一性的,可使用其构造字典return list(map(frozenset, C1))     # 从候选K项集到频繁K项集(支持度计算)
def scanD(D, Ck, minSupport):ssCnt = {}for tid in D:   # 遍历数据集for can in Ck:  # 遍历候选项if can.issubset(tid):  # 判断候选项中是否含数据集的各项if not can in ssCnt:ssCnt[can] = 1  # 不含设为1else:ssCnt[can] += 1  # 有则计数加1numItems = float(len(D))  # 数据集大小retList = []  # L1初始化supportData = {}  # 记录候选项中各个数据的支持度for key in ssCnt:support = ssCnt[key] / numItems  # 计算支持度if support >= minSupport:retList.insert(0, key)  # 满足条件加入L1中supportData[key] = support  return retList, supportDatadef calSupport(D, Ck, min_support):dict_sup = {}for i in D:for j in Ck:if j.issubset(i):if not j in dict_sup:dict_sup[j] = 1else:dict_sup[j] += 1sumCount = float(len(D))supportData = {}relist = []for i in dict_sup:temp_sup = dict_sup[i] / sumCountif temp_sup >= min_support:relist.append(i)
# 此处可设置返回全部的支持度数据(或者频繁项集的支持度数据)supportData[i] = temp_supreturn relist, supportData# 改进剪枝算法
def aprioriGen(Lk, k):retList = []lenLk = len(Lk)for i in range(lenLk):for j in range(i + 1, lenLk):  # 两两组合遍历L1 = list(Lk[i])[:k - 2]L2 = list(Lk[j])[:k - 2]L1.sort()L2.sort()if L1 == L2:  # 前k-1项相等,则可相乘,这样可防止重复项出现# 进行剪枝(a1为k项集中的一个元素,b为它的所有k-1项子集)a = Lk[i] | Lk[j]  # a为frozenset()集合a1 = list(a)b = []# 遍历取出每一个元素,转换为set,依次从a1中剔除该元素,并加入到b中for q in range(len(a1)):t = [a1[q]]tt = frozenset(set(a1) - set(t))b.append(tt)t = 0for w in b:# 当b(即所有k-1项子集)都是Lk(频繁的)的子集,则保留,否则删除。if w in Lk:t += 1if t == len(b):retList.append(b[0] | b[1])return retListdef apriori(dataSet, minSupport=0.2):
# 前3条语句是对计算查找单个元素中的频繁项集C1 = createC1(dataSet)D = list(map(set, dataSet))  # 使用list()转换为列表L1, supportData = calSupport(D, C1, minSupport)L = [L1]  # 加列表框,使得1项集为一个单独元素k = 2while (len(L[k - 2]) > 0):  # 是否还有候选集Ck = aprioriGen(L[k - 2], k)Lk, supK = scanD(D, Ck, minSupport)  # scan DB to get LksupportData.update(supK)  # 把supk的键值对添加到supportData里L.append(Lk)  # L最后一个值为空集k += 1del L[-1]  # 删除最后一个空集return L, supportData  # L为频繁项集,为一个列表,1,2,3项集分别为一个元素# 生成集合的所有子集
def getSubset(fromList, toList):for i in range(len(fromList)):t = [fromList[i]]tt = frozenset(set(fromList) - set(t))if not tt in toList:toList.append(tt)tt = list(tt)if len(tt) > 1:getSubset(tt, toList)def calcConf(freqSet, H, supportData, ruleList, minConf=0.7):for conseq in H:  #遍历H中的所有项集并计算它们的可信度值conf = supportData[freqSet] / supportData[freqSet - conseq]  # 可信度计算,结合支持度数据# 提升度lift计算lift = p(a & b) / p(a)*p(b)lift = supportData[freqSet] / (supportData[conseq] * supportData[freqSet - conseq])if conf >= minConf and lift > 1:print(freqSet - conseq, '-->', conseq, '支持度', round(supportData[freqSet], 6), '置信度:', round(conf, 6),'lift值为:', round(lift, 6))ruleList.append((freqSet - conseq, conseq, conf))# 生成规则
def gen_rule(L, supportData, minConf = 0.7):bigRuleList = []for i in range(1, len(L)):  # 从二项集开始计算for freqSet in L[i]:  # freqSet为所有的k项集# 求该三项集的所有非空子集,1项集,2项集,直到k-1项集,用H1表示,为list类型,里面为frozenset类型,H1 = list(freqSet)all_subset = []getSubset(H1, all_subset)  # 生成所有的子集calcConf(freqSet, all_subset, supportData, bigRuleList, minConf)return bigRuleListif __name__ == '__main__':dataSet = data_translationL, supportData = apriori(dataSet, minSupport = 0.02)rule = gen_rule(L, supportData, minConf = 0.35)

结果如下

frozenset({'水果/蔬菜汁'}) --> frozenset({'全脂牛奶'}) 支持度为0.02664 置信度:0.368495 life值为:1.44216 为例可得:顾客同时购买水果、蔬菜汁和全脂牛奶这3种商品的概率约为36.85%,而这种情况发生的可能性约为2.66%

综合分析可得顾客同时购买其他蔬菜、根茎类蔬菜和全脂牛奶的概率较高。

python数据分析与挖掘实战(商品零售购物篮分析)相关推荐

  1. 数据挖掘实战—商品零售购物篮分析

    文章目录 引言 一.数据探索性分析 1.数据质量分析 1.1 缺失值分析 1.2 异常值分析 1.3 重复数据分析 2.数据特征分析 2.1 描述性统计分析 2.2 分布分析 2.2.1 商品热销情况 ...

  2. R语言小代码(商品零售购物篮分析)

    任务: 某西饼屋准备对现有的店面重新进行布置,以期能够给用户提供更加友好的体验.现有某西饼屋某天60天订单数据,部分数据如下所示,使用Apriori算法对西饼屋订单进行关联分析. 一.导入数据: se ...

  3. 大数据培训课程分享:Python数据分析与挖掘实战课程介绍

    <Python数据分析与挖掘实战>课程内容以Python数据分析与挖掘的常用技术与真实案例相结合的方式,深入浅出地介绍Python数据分析与挖掘的重要内容,共分为基础篇(第1~5章)和实战 ...

  4. python数据分析与挖掘实战 之笔记2

    <python数据分析与挖掘实战>学习笔记2 经过前面章节的分析,即对数据进行探索和预处理,得到了处理后的数据.根据所得到的数据建立分类与预测.聚类分析.关联规则.时序模式.和偏差检测等模 ...

  5. 《Python数据分析与挖掘实战》一3.1 数据质量分析

    本节书摘来自华章出版社<Python数据分析与挖掘实战>一书中的第3章,第3.1节,作者 张良均 王路 谭立云 苏剑林,更多章节内容可以访问云栖社区"华章计算机"公众号 ...

  6. 《Python数据分析与挖掘实战》一第1章 数据挖掘基础1.1 某知名连锁餐饮企业的困惑...

    本节书摘来自华章出版社<Python数据分析与挖掘实战>一书中的第1章,第1.1节,作者 张良均 王路 谭立云 苏剑林,更多章节内容可以访问云栖社区"华章计算机"公众号 ...

  7. 《Python数据分析与挖掘实战》一1.2 从餐饮服务到数据挖掘

    本节书摘来自华章出版社<Python数据分析与挖掘实战>一书中的第1章,第1.2节,作者 张良均 王路 谭立云 苏剑林,更多章节内容可以访问云栖社区"华章计算机"公众号 ...

  8. 《Python数据分析与挖掘实战》第7章-聚类+绘制雷达图

    本文是基于<Python数据分析与挖掘实战>的第七章的数据--<航空公司客户价值分析>做的分析对部分代码,做出补充,对原文中的雷达图进行了实现. 1. 背景与目标分析 此项目旨 ...

  9. (八)Python数据分析与挖掘实战(实战篇)——中医证型关联规则挖掘

    这个专栏用来记录我在学习和实践<Python数据分析与挖掘实战>一书时的一些知识点总结和代码实现. 文章目录 背景和目标 数据 原始属性表 脚本 discretization.py apr ...

最新文章

  1. Linux配置文件bashrc
  2. 清华唐杰:GPT-3表示能力已经接近人类了,但它有一个阿喀琉斯之踵 | MEET 2021
  3. Java基础之多线程详细分析
  4. Web离线应用解决方案——ServiceWorker
  5. asp.net的get和post请求
  6. MongoDB 入门篇
  7. 星座图(2020特长生 T4)
  8. 科学家对医疗预印本服务器的影响,美国化学学会将启动化学论文预印本服务
  9. win7 更新android sdk,大神为你详解win7系统android sdk manager无法更新的处理对策
  10. 在虚拟机上安装Kali Linux的简易指南
  11. 智能优化算法:黏菌优化算法 - 附代码
  12. 在Ubuntu 20.04上安装MySQL教程
  13. 国内薪水最高的IT公司排行榜TOP25,大家都说说你们觉得这数据准确吗,我怎么觉得不太准确。。
  14. 百钱买百鸡 假设公鸡5文钱一只 母鸡三文钱一只 小鸡1文钱三只,要求用100文钱 , 如何买到100只鸡
  15. The Derivation About CNN and Antoencoder
  16. eclips 快捷键大全
  17. DBCO-PEG-TAT DBCO-聚乙二醇-TAT
  18. 企业中流砥柱:别让企业中层缺位
  19. PAT甲级 A1042
  20. 深度剖析使用ROS系统开发机器人的好处

热门文章

  1. 分式化简结果要求_分式化简的结果有什么要求?
  2. matlab 分式,MATLAB怎样把该式子化成咱们常用的分式结构
  3. 基于TCP/IP协议 区别 GET和POST
  4. loadrunner入门教程(31) --Analysis
  5. 墨者学院-密码学加解密实训(摩斯密码第2题)
  6. POJO VO PO DTO 和JavaBean
  7. 微信小程序 - 登录获取openid和用户信息(适配getUserProfile)
  8. 如何彻底关掉pycharm的警告
  9. shell-判断两个ip是否在同一个网段
  10. Vanish搭建CDN的节点集群