关联规则算法怎么实现?Python代码、PowerBI可视化详细解释给你听(下-实战篇)

在上一篇中,我讲解了关联规则的原理和实现步骤,如果大家看懂了,其实很好理解。但是说起来容易做起来难,如何通过工具将原始数据处理得到有效可靠的结果还是会存在问题。实际工作是让你解决问题而不只是说出解决思路。本篇就是在理论的基础上,结合实际数据来展示如何使用Python实现关联规则和如何在PowerBI中导入Python脚本生成数据表并以可视化的方式动态展示。

        在使用Python解决某个问题时,其实并不是从0到1一步一步搭建,这个过程很繁琐,有时候为了实现一个小小的效果可能得绕很大的弯,所以就跟“调参侠”一样,我们往往使用别的搭好的梯子。这也是为什么Python语言这么受欢迎,因为它有很完善的开源社区和不计其数的工具库库来实现某个目的。我们在实现计算关联规则时,使用的是机器学习库mlxtend中的apriori,fpgrowth,association_rules算法。         apriori 是一种流行的算法,用于在关联规则学习中应用提取频繁项集。apriori 算法旨在对包含交易的数据库进行操作,例如商店客户的购买。如果满足用户指定的支持阈值,则项集被认为是“频繁的”。例如,如果支持阈值设置为 0.5 (50%),则频繁项集被定义为在数据库中至少 50% 的所有事务中一起出现的一组项目。

一、数据集

#导入相关的库import pandas as pd   
import mlxtend  #机器学习库#编码包
from mlxtend.preprocessing import TransactionEncoder  #关联规则计算包
from mlxtend.frequent_patterns import apriori, fpmax, fpgrowth,association_rules
pd.set_option('max_colwidth',150)  #对pandas显示效果设置,列显示字段长度最长为150个字符          
#导入数据集Order = pd.read_excel("D:/orders.xlsx")
#查看数据集的大小Order.shape
#查看数据前10行Order.tail(5)

        数据集中有121253条数据,总共有四个字段,SalesOrderNumber是指订单号;ordernumber是指子订单号,下换线加数字表明是订单的第几个子订单,每个订单号下可能有一个或多个子订单,而每个子订单是不重复的,对应一个产品;Product是指商品名称。

二、mlxtend

        在实际开始前我们先来了解这个mlxtend中的包怎么用的。在mlxtend官网上演示了如何实现关联规则的计算,我们来看一下总共有三步:
        第一步,导入apriori算法包;
        第二步,将原始订单数据处理成算法支持的格式;         第三步,计算支持度、置信度、提升度等指标并筛选强规则。

第一步:导入apriori算法包

第二步,将原始订单数据处理成算法支持的格式:

        在实际获取到的数据往往是我上一篇中举例那样,订单号后以列表的形式排列商品。所以mlxtend包接受这样数据格式。但是用于计算却不能直接这样用,一是真实数据都是文本,二是apriori算法包需要一个将原始数据转化为商品独热编码的Pandas Dataframe格式。以下是输入数据:

        它使用TransactionEncoder包来将输入数据转换成我们需要的形式。以下是转换的代码和结果:

        接下来,它将处理好的数据格式喂给apriori算法包,计算频繁项集(itemsets)和支持度。根据自己预先设定的最小支持度为0.6来排除非频繁项集。

        然而上面有个问题,上面返回的结果集是数字,其实是df表里每个项(item)的索引,这对于后面处理比较方便,但是如果只想用这个结果。为了增加可读性,可以使用use_colnames=True的参数来显示原本的商品名。

第三步,计算支持度、置信度、提升度

        这里没有在apriori算法包里演示第三步,这是为什么呢?因为apriori算法包只是关联规则里的第一步--找频繁项集,当然不会发现强关联规则啦!这一步是在另一个包association_rules里实现的。这里也是很多初学者会容易出现的问题,不知道各个包的用法,不清楚怎么调用包。

        这样我们就算出了所有符合最小支持度的频繁项集的支持度、置信度、提升度,上面还出现leverage和conviction,这两个的作用同提升度lift的作用是一样的,之前我讲过最好使用KLUC度量和IR不平衡比例,不过显然mlxtend的开发者更喜欢使用leverage和conviction,这里先不管它。本案例只演示使用支持度lift。

三、Python实现关联规则代码

第一步,生成格式数据

        以上是官网给出的关联规则包用法。接下来我用自己的数据集实际操作,并演示如何在PowerBI中导入Python脚本生成数据表并以可视化的方式动态展示。上面已经给出了示例数据。可以看到数据集是每个订单有多个商品,但是一行一行的,不是一个订单后面一行接所以商品的形式。所以这里要想办法从行转换到列。这里使用Pandas中的分组功能,要实现的效果如下:

#使用DataFrame的groupby函数
group_df = Order.groupby(['SalesOrderNumber'])

         如果大家会写SQL的话应该知道groupby分组必须与聚合函数一起结合使用,因为它是一个mapreduce的过程。如果按订单号分组而没有使用聚合函数的话,在SQL Server中会报错,在Mysql中只会返回第一行数据。而这里直接使用了groupby分组没有用聚合函数,这不会有什么问题吗?我们来看一下结果group_df:

group_df.head(2) #查看数据集

        上面这张图是把groupby后的结果(本以为返回的是数据集),分别去取前2个和前5个来看,结果发现返回的数据不一样和数据集大小也不一样(注意我们最开始查看数据显示的是121253条数据)。实际上这个groupby后的结果是一个生成器,它返回的是动态的分组过程,如果要使用结果可以喂不同的参数来获取实际结果。所以就利用这个功能来实现group_oncat,生成商品列表。

df_productlist = pd.DataFrame({"productlist":group_df['Product'].apply(list)}).reset_index()df_productlist.head(5)

        上面这段代码的意思是生成一张新表,这张表是有按照SalesOrderNumber分组,然后将每个订单组的Product按照列表聚合在一起;这张表只有了两列,一列是分组依据SalesOrderNumber,另一列命名为productlist;最后将原数据标的索引去掉,重置索引,最后得到df_productlist表,这样我们就形成了算法接受的输入数据格式。下面是查看前5行的结果:

#因为只需要频繁项集,所以这里去掉订单号,将productlist转为numpy数组格式。
df_array = df_productlist["productlist"].tolist() 
df_array[0:3]  #取前三个查看

        可以看到形成了输入数据,我们再使用TransactionEncoder对数据进行处理,生成每个商品(项)的独热编码DataFrame格式:

trans= TransactionEncoder()  #调用编码包
trans_array = trans.fit_transform(df_array)  #将数据集喂进编码包进行转换
df_item = pd.DataFrame(trans_array, columns=trans.columns_)  #将转换好的数据转成DataFrame格式
df_item.head()

第二步,生成频繁项集

        生成最终数据格式后,将数据喂给apriori算法包生成频繁项集:

#给定最小支持度为0.01,显示列名
frequent_itemset = apriori(df_item,min_support=0.01,use_colnames=True)  
frequent_itemset.tail(5)

        算法生成的结果也是DataFrame格式的频繁项集,它会把频繁1项集、频繁2项集、频繁3项集等所有大于等于最小支持度的结果返回。这里显示的是频繁1项集。

        实际上为了便于我们查看和筛选,还可以对频繁项集的长度进行计数,从而可以动态索引。

frequent_itemset['length'] = frequent_itemset['itemsets'].apply(lambda x: len(x))frequent_itemset[ (frequent_itemset['length'] == 2) &(frequent_itemset['support'] >= 0.01) ]

        这段代码的意思是找出支持度大于等于0.01的频繁2项集,也就是我们常常关心的顾客买了一个商品,还会买哪个商品的情况。

上面完成了第一步频繁项集的生成之后,下面就是挖掘关联规则。

第三步,计算支持度、置信度、提升度

association = association_rules(frequent_itemset,metric="confidence",min_threshold=0.01)association.head()

        上面这张表显示共找到了169034个可供选择的关联规则,列名分别是什么意思呢?
antecedents:表示先购买的产品(组合),consequents表示后购买的产品(组合);
antecedent support:表示先购买的产品(组合)占所有订单的支持度;
consequent support:表示后购买的产品(组合)占所有订单的支持度;
support:表示同时购买两个产品(组合)的情况占所有订单的支持度;
confidence:表示同时购买两个产品(组合)的情况占所有订单的支持度与antecedent support的比值,也就是规则的置信度;lift:表示的是confidence与consequent support的比值,也就是提升度,验证先购买的产品(组合)再购买B产品组合的可能性的有效性;

        最后我们只关注买了一件再买一件和买了两件再买一件的情况,这是最常见的实际场景需求。所以生成两张表df_BuyAB和df_BuyABC。以下是完整代码,如果你有相同格式的数据集,可以直接跑通这个算法。

import pandas as pd
import mlxtend
from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import apriori, fpmax, fpgrowth,association_rules
Allorder = pd.read_excel("D:/4_MySQL/AdventureWorksDW2012/Allorder.xlsx")
group_df = Allorder.groupby(['SalesOrderNumber'])
df_productlist = pd.DataFrame({"productlist":group_df['Product'].apply(list)}).reset_index()
df_array = df_productlist["productlist"].tolist()
trans= TransactionEncoder()
trans_array = trans.fit_transform(df_array)
df_association = pd.DataFrame(trans_array, columns=trans.columns_)
frequent_itemset = apriori(df_association,min_support=0.01,use_colnames=True)
association = association_rules(frequent_itemset,metric="confidence",min_threshold=0.01)
BuyAB = association[(association['antecedents'].apply(lambda x :len(x)==1)) & (association['consequents'].apply(lambda x :len(x)==1))]
BuyABC = association[(association['antecedents'].apply(lambda x :len(x)==2)) & (association['consequents'].apply(lambda x :len(x)==1))]

        文章开头的视频展示的是如何利用这个Python脚本实现动态可视化,以便于业务人员使用,提高销售业绩。如果文章开头没有视频,可以去我的知乎上查看。

        最后欢迎大家关注我,我是拾陆,搜索公号“二八Data”,更多技术干货持续奉献。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容