Python金融数据挖掘 第八章 复习思考题2
一、问题
设有一份购物篮数据basketdata.txt,包括两部分内容。
本部分收集了1000位顾客的相关信息资料,并包含七个关键指标:每位顾客的会员卡号(cardid)、消费金额(value)、采用的方式进行支付(pmethod)、性别信息(sex),其中M代表男性而F代表女性;是否为家庭主(homeown);以及每位客人的年龄(age)与收入水平(income)。
第二部分包含1,000名顾客在单次购物中所涉及的商品信息。每个商品变量均为二元分类型变量,在赋值上采用如下方式:赋值为1表明该商品被选中;赋值为0则表示未被选中。这些商品变量具体包括:如水果与蔬菜(fruit and vegetable)、新鲜肉类(fresh meats)、乳制品(dairy products)、罐装蔬菜(canned vegetables)、罐装肉类(canned meats)、冷冻食品类(frozen meal items)、啤酒品牌(beer brands)、干白葡萄酒(dry white wine)、非酒精型饮料(non-alcoholic beverages)、各种鱼类产品(various types of fish products),以及糖果与巧克力制品等特定类别。基于这一数据集结构,请问您希望我们利用关联规则分析算法完成以下任务?
(1)找到有较大可能连带销售 的商品。
(2)比较不同性别与年龄段组合下的消费者对啤酒的选择偏好。(这里将年龄划分为三个阶段:30岁以下定义为青年群体"1"、30~49岁界定为中年群体"2"、50岁以上归类为老年群体"3"。)
二、代码
'''
我是第二题
我是第二题
'''
##################2
import pandas as pd
import numpy as np
# 打开txt文件
f = open("basketdata1.txt","r",encoding='utf-8') #设置文件对象
# 转换为二维表格式
ff= []
line = []
for line in f.readlines():#readlines以列表输出文件内容
line = line.strip().split("\t")
line1 = " ".join(line)
line1 = line1.split(",")
# result.append(line)
ff.append(line1)
f.close() #将文件关闭
f1=pd.DataFrame(ff).dropna(axis=0)
# 添加列名
f1.columns= ['cardid','value','pmethod','sex','homeown','income','age','fruitveg','freshmeat','dairy','cannedveg','cannedmeat','frozenmeal','beer','wine','softdrink','fish','confectionery']
# f1.columns= ['cardid','value','pmethod','sex','homeown','income','age',1,2,3,4,5,6,7,8,9,10,11]
# print(f1.head())
# TF转换为商品信息
def val2colindex(val,colname):
if(val=='T'):
return colname
else:
return 0
for i in f1.columns[7:]:
f1[i]=f1[i].apply(lambda val:val2colindex(val,i))
# print(f1.head())
(1)找到有较大可能连带销售 的商品。
###############(1)
# 数据
def loadDataSet():#函数,基础知识
# mm = np.array(f1[lambda f1: f1.columns[7:]]).tolist()
mm = f1[lambda f1: f1.columns[7:]]
data2Dlist = []
for index,row in mm.iterrows():
list1=row.tolist()
# list1.pop(0)
while 0 in list1:
list1.remove(0)
if list1!=[]:
data2Dlist.append(list1)
else:
continue
return data2Dlist
D=loadDataSet()
# print(D)
def createC1(dataSet):
C=[]
for transaction in dataSet:
for item in transaction:
if [item] not in C:
C.append([item])
C.sort()
#调用frozenset函数将单项集列表冻结,返回冻结单项集列表
return list(map(frozenset,C))
def scanD(D,Ck,minSupport):
ssCnt={}
#对于每一个候选项集can,检查是否是D的一部分,即该候选can是否得到transcaction的支持
for tid in D:
for can in Ck:
if can.issubset(tid):
ssCnt[can]=ssCnt.get(can,0)+1
numItems=float(len(D))
retList=[]
supportData={}
for key in ssCnt:
#每个项集的支持度
support=ssCnt[key]/numItems
#将满足最小支持度的项集,加入retList中
if support>=minSupport:
retList.insert(0,key)
#汇总支持度数据
supportData[key]=support
return retList,supportData
#拼接函数,输入为Ck-1、K参数,表示生成k-项集
def aprioriGen(Ck,k):
retList=[]
lenCk=len(Ck)
#以下的Ck[i]与Ck[j]均包含k-1个项,如果它们的前k-2项相同
#则通过或运算将其拼接为一个包含k项的列表元素,加入到retList中
for i in range(lenCk):
for j in range(i+1,lenCk):
L1=list(Ck[i])[:k-2]
L2=list(Ck[j])[:k-2]
L1.sort()
L2.sort()
if L1 == L2:
retList.append(Ck[i]|Ck[j])
return retList
#生成所有的频繁项集L1,及所有项集的支持度
#输入为交易记录D,及最小支持度参数minSupport
def apriori(D,minSupport):
C1=createC1(D)
L1,suppData=scanD(D,C1,minSupport)
L=[L1]
#最初的L1中的每个项集含有一个元素
#新生成的项集应该含有2个元素,所以k=2
k=2
while(len(L[k-2])>0):
Ck=aprioriGen(L[k-2],k)
Lk,supK=scanD(D,Ck,minSupport)
#将新的项集的支持度数据加入原来的总支持度字典中
suppData.update(supK)
#将符合最小支持度要求的项集加入L
L.append(Lk)
#新生成的项集中的元素个数应不断增加
k+=1
#返回所有满足条件的频繁项集的列表和所有候选项集的支持度信息
return L,suppData
# L1,suD2=apriori(D,0.315)
# # print(L1)
# print(suD2)
# 删除
# print("据suD2可知:('frozenmeal', 'cannedveg'),(frozenmeal', 'fruitveg'),('cannedveg', 'fruitveg')在支持度为0.313时,具有较大可能连带销售。")
L1,suD2=apriori(D,0.1)
def calcConf(freqSet,H,supportData,brl,minConf=0.6):
prunedH=[]
for conseq in H:
conf=supportData[freqSet]/supportData[freqSet-conseq]
if conf >= minConf:
print(freqSet-conseq,'-->',conseq,'conf:',conf)
brl.append((freqSet - conseq,conseq,conf))
prunedH.append(conseq)
return prunedH
def rulesFromConseq(freqSet,H,supportData,brl,minConf=0.6):
m=len(H[0])
#检查频繁项集是否大到移除大小为m的子集
if len(freqSet)>m+1:
Hmp1=aprioriGen(H,m+1)
Hmp1=calcConf(freqSet,Hmp1,supportData,brl,minConf)
#如果不止一条规则满足要求,进一步递归合并
if len(Hmp1)>1:
rulesFromConseq(freqSet,Hmp1,supportData,brl,minConf)
def generateRules(L,supportData,minConf=0.6):
bigRuleList=[]
for i in range(1,len(L)):
for freqSet in L[i]:
#对于每一个频繁项集的集合freqSet
H1=[frozenset([item]) for item in freqSet]
#如果频繁项集中的元素个数大于2,需要进一步合并
if i>1:
rulesFromConseq(freqSet,H1,supportData,bigRuleList,minConf)
else:
calcConf(freqSet,H1,supportData,bigRuleList,minConf)
# return bigRuleList
bRlist=generateRules(L1,suD2,0.5)
print('相关度大于50%的物品及置信度:')
print(bRlist)
print("相关度大于50%的物品及置信度:{'wine','confectionery'},{'confectionery','wine'},{'cannedveg','beer'},{'beer','cannedveg'},{'frozenmeal','beer'},{'cannedveg','frozenmeal'},{'frozenmeal','cannedveg'}")
对性别与年龄层次之间的顾客酒类选择趋势展开分析研究。(具体而言,在研究过程中按照年龄划分三个群体:将年轻群体定义为编号1(小于30岁),中年群体标记为编号2(介于30至49岁之间),而老年群体赋值编号3(50岁以上)。)
#############################(2)
# 年龄段分组
for i in range(len(f1)):
if int(f1['age'][i]) < 30:
f1['age'][i] = 1
elif int(f1['age'][i]) <=49:
f1['age'][i] = 2
else:
f1['age'][i] = 3
# 分组
aaaa = f1.groupby(['sex','age'])['beer'].agg('count')
bbbb = pd.DataFrame(aaaa)
print(bbbb)
print('由数据可以看出,无论男女,年龄位于1、2两组,及50岁以下的顾客较倾向购买啤酒,而50岁以上的顾客很少购买。')
