目录
赛题背景
赛题数据
赛题任务
1、导入数据
2、数据探索
3、采用efficient_apriori算法挖掘频繁项集和频繁规则
4、 绘制频繁项集的条形图
赛题以购物篮分析为背景,要求选手对品牌的历史订单数据,挖掘频繁项集与关联规则。通过这道赛题,鼓励学习者利用订单数据,为企业提供销售策略,产品关联组合,为企业提升销量的同时,也为消费者提供更适合的商品推荐。
数据源:order.csv,product.csv,customer.csv,date.csv ,分别为订单表,产品表,客户表,日期表
现在需要你使用关联分析(比如Apriori算法) 挖掘订单中的频繁项集及关联规则
说明:
1)频繁项集、关联规则的计算会用到支持度、置信度、提升度等指标,
2)频繁项集:即大于最小支持度的商品或商品组合
3)关联规则:在频繁项集中,满足最小置信度,或最小提升度的推荐规则
(这里最小支持度、最小置信度或最小提升度,选手可以根据数据集的特点自己设定)
!pip install efficient_apriori --user
'''在天池实验室做的,下载用!pip install efficient_apriori --user,如果在本地直接pip install efficient_apriori'''
import pandas as pd
import time
import matplotlib.pyplot as plt
from matplotlib import font_manager
#设置正常显示字体
font_manager.fontManager.addfont('./SimHei.ttf')
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置汉字字体,优先使用黑体
plt.rcParams['font.size'] = 12 # 设置字体大小
plt.rcParams['axes.unicode_minus'] = False # 设置正常显示负号
df_order = pd.read_csv('./order.csv',encoding='gbk')
df_product = pd.read_csv('./product.csv',encoding='gbk')
df_customer = pd.read_csv('./customer.csv',encoding='gbk')
daf_date = pd.read_csv('./date.csv',encoding='gbk')
df_order.head()
df_order['订单日期']=pd.to_datetime(df_order['订单日期']) #将原表内订单日期转化为pandas日期格式
print(df_order.head())
print(df_order.info())
RangeIndex: 60398 entries, 0 to 60397 Data columns (total 17 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 订单日期 60398 non-null datetime64[ns] 1 年份 60398 non-null int64 2 订单数量 60398 non-null int64 3 产品ID 60398 non-null int64 4 客户ID 60398 non-null object 5 交易类型 60398 non-null int64 6 销售区域ID 60398 non-null int64 7 销售大区 60398 non-null object 8 国家 60398 non-null object 9 区域 60398 non-null object 10 产品类别 60398 non-null object 11 产品型号名称 60398 non-null object 12 产品名称 60398 non-null object 13 产品成本 60398 non-null float64 14 利润 60398 non-null float64 15 单价 60398 non-null float64 16 销售金额 60398 non-null float64 dtypes: datetime64[ns](1), float64(4), int64(5), object(7) memory usage: 7.8+ MB
#探索重复客户ID数量
print(df_order['客户ID'].value_counts())
13206BA 68 13321BA 67 13298BA 65 13283BA 63 13308BA 62 .. 31444BA 1 13428BA 1 18295BA 1 30732BA 1 30480BA 1 Name: 客户ID, Length: 18484, dtype: int64
#探索重复产品名称数量
print(df_order['产品名称'].value_counts())
棒球手套 17332 硬式棒球 8068 球棒与球棒袋 7981 头盔 6440 软式棒球 4970 棒球服 3332 帽子 2190 垒球 2167 三角网架 2121 击打手套 1430 皮带 1019 垒垫 908 装备包 733 袜子 568 捕手护具 562 球网 328 打击T座 249 Name: 产品名称, dtype: int64
# 探索是否存在同一订单日期且客户ID也相同的情况,若存在则合并该天内该客户购买的所有产品
df_order=df_order.groupby(['客户ID','订单日期'])['产品名称'].unique()
print(df_order)
客户ID 订单日期 13021BA 2013-07-22 [软式棒球] 2015-07-22 [三角网架, 软式棒球] 2015-11-04 [垒球, 棒球服, 头盔, 棒球手套] 13022BA 2013-07-18 [软式棒球] 2015-07-20 [球棒与球棒袋, 软式棒球, 三角网架, 帽子, 棒球服] Name: 产品名称, dtype: object
#将所有交易追加到同一个交易列表中,每一个交易是同一个客户同一天购买的所有产品的集合
transactions=[]
for value in df_order:
transactions.append(list(value))
# print(transactions)
from efficient_apriori import apriori
# 单个transaction定义为同一天内同一客户ID购买的所有产品
start = time.time()
itemsets, rules = apriori(transactions, min_support=0.03, min_confidence=0.05)
print('频繁项集:', itemsets)
print('关联规则:', rules)
end = time.time()
print("用时:", end - start)
频繁项集: {1: {('软式棒球',): 4970, ('三角网架',): 2121, ('垒球',): 2167, ('棒球服',): 3332, ('头盔',): 6439, ('棒球手套',): 9844, ('球棒与球棒袋',): 4767, ('帽子',): 2190, ('硬式棒球',): 8068, ('击打手套',): 1430, ('皮带',): 1019, ('垒垫',): 908}, 2: {('三角网架', '软式棒球'): 898, ('垒球', '头盔'): 893, ('头盔', '棒球手套'): 2769, ('头盔', '球棒与球棒袋'): 1203, ('头盔', '硬式棒球'): 1353, ('头盔', '软式棒球'): 934, ('棒球手套', '硬式棒球'): 909, ('棒球手套', '软式棒球'): 910, ('球棒与球棒袋', '硬式棒球'): 986, ('球棒与球棒袋', '软式棒球'): 948}} 关联规则: [{软式棒球} -> {三角网架}, {三角网架} -> {软式棒球}, {头盔} -> {垒球}, {垒球} -> {头盔}, {棒球手套} -> {头盔}, {头盔} -> {棒球手套}, {球棒与球棒袋} -> {头盔}, {头盔} -> {球棒与球棒袋}, {硬式棒球} -> {头盔}, {头盔} -> {硬式棒球}, {软式棒球} -> {头盔}, {头盔} -> {软式棒球}, {硬式棒球} -> {棒球手套}, {棒球手套} -> {硬式棒球}, {软式棒球} -> {棒球手套}, {棒球手套} -> {软式棒球}, {硬式棒球} -> {球棒与球棒袋}, {球棒与球棒袋} -> {硬式棒球}, {软式棒球} -> {球棒与球棒袋}, {球棒与球棒袋} -> {软式棒球}] 用时: 0.016688108444213867
itemsets_item=[] #获取横坐标,频繁项集产品名称的列表
itemsets_count=[] #获取纵坐标,频繁项集产品名称出现的频数的列表
for key in itemsets.keys():
df1=itemsets[key]#df1 = 每个索引对应的频繁项集
'''key = 1时,df1 = {('软式棒球',): 4970, ('三角网架',): 2121, ('垒球',): 2167, ('棒球服',): 3332, ('头盔',): 6439, ('棒球手套',): 9844,
('球棒与球棒袋',): 4767, ('帽子',): 2190, ('硬式棒球',): 8068, ('击打手套',): 1430, ('皮带',): 1019, ('垒垫',): 908}'''
for key in df1:
itemsets_item.append(key)#频繁项集产品名称
itemsets_count.append(df1[key])#频繁项集产品名称出现的频数
itemsets_itemstr=[] #将横坐标转化为字符串形式
for i in itemsets_item:
itemsets_itemstr.append(','.join(list(i)))
print(itemsets_itemstr)
print(itemsets_count)
['软式棒球', '三角网架', '垒球', '棒球服', '头盔', '棒球手套', '球棒与球棒袋', '帽子', '硬式棒球', '击打手套', '皮带', '垒垫', '三角网架,软式棒球', '垒球,头盔', '头盔,棒球手套', '头盔,球棒与球棒袋', '头盔,硬式棒球', '头盔,软式棒球', '棒球手套,硬式棒球', '棒球手套,软式棒球', '球棒与球棒袋,硬式棒球', '球棒与球棒袋,软式棒球'] [4970, 2121, 2167, 3332, 6439, 9844, 4767, 2190, 8068, 1430, 1019, 908, 898, 893, 2769, 1203, 1353, 934, 909, 910, 986, 948]
plt.bar(itemsets_itemstr,itemsets_count)
plt.xlabel('频繁项集_产品名称',fontsize=14) #设置X轴标签
plt.ylabel('频繁项集_出现频数',fontsize=14) #设置Y轴标签
plt.title('频繁项集频数分布柱状图',fontsize=18) #为柱状图添加标题
plt.xticks(rotation=90,fontsize=10) #设置X轴内容竖排显示
for a, b in zip(itemsets_itemstr, itemsets_count): #设置数据标签可见
plt.text(a, b + 0.005, str(b), ha='center', va='bottom', fontsize=8)
plt.show()
频繁模式挖掘及Python实现