栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

数据分析六、案例实战---Apr 算法之公众号关联分析

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

数据分析六、案例实战---Apr 算法之公众号关联分析

案例实战---Apr 算法之公众号关联分析
  • 一、案例背景
  • 二、明确目标
  • 三、数据处理
    • 3.1关于数据清洗,略...
    • 3.2数据整理
  • 四、数据分析
  • 五、数据展现
    • 5.1 绘制多组柱状图
    • 5.2案例展现
      • 5.2.1紧接前面提取到含有促进关系(提升度大于 1)的强关联规则,我先来画一下它的支持度及置信度的双组柱状图。
      • 5.2.2绘制提升度小于 1 的关联规则柱状图。
      • 5.2.3 绘制所有强关联规则的提升度柱状图:
  • 总结:

一、案例背景

订阅号每天只能推送一次,一次最多可以发 8 篇图文,但这 8 篇文章必须打包在一块,一个含有大海报&大标题的“头条”,以及7个“次条”。公司的业务范围正在迅速扩大,所以在推送文章时,需要考虑到文章类型的多样性,因此,每天的推送排版,他都要考虑不同的文章类型之间的契合性。
要是陈列不当,次条的阅读量就很惨淡。当然,要是选择恰当,头条和次条就能相互促进,表现喜人,只是,这并不常见。
头条一般都是确定的,主要是次条文章的挑选。那针对不同类型的头条文章,到底应该怎么罗列订阅号的“次条”比较好呢?或者,换句话说,读者可能会同时喜欢看什么类型的内容呢?

二、明确目标

那公众号阅读行为能否像用户的购买行为一样,能挖掘出不同类型文章之间的关联关系?
答案是肯定的。但问题的关键是,怎么定义阅读行为?
在订阅号的场景下,可以将用户在一天内看的所有文章当作是用户的一次阅读行为。
通过对用户阅读行为的关联分析,就能更多地了解顾客的阅读习惯,从而为订阅号每日推文的组合提供参考。
基于这一目标,以及使用 Apr 算法实现关联分析的流程,我们拆解到如下三个分目标:

从运营那我们拿到了一份记录用户阅读轨迹的数据。公众号用户访问数据.csv

In [ 37 ]
1 import pandas as pd
2 # 以 gbk 的编码模式读取并查看【公众号用户访问数据.csv】数据
3 user_data = pd.read_csv('./工作/公众号用户访问数据.csv',encoding='gbk')
4 user_data
运行
Out [ 37 ]
用户编号	文章类别	阅读数	看一看	点赞	赞赏	被转载	访问日期
0	1	数据分析	20051	1203	2406	80	601	2020/9/21
1	2	数据分析	11690	584	1519	46	233	2020/9/17
2	3	数据分析	5720	400	572	45	228	2020/9/2
3	4	数据分析	22502	1125	3150	45	900	2020/9/24
4	5	数据分析	11201	560	1344	89	448	2020/9/8
...	...	...	...	...	...	...	...	...
194	98	pandas	7454	521	819	29	223	2020/9/20
195	98	pandas	7587	379	910	22	151	2020/9/20
196	99	数据分析	12179	852	1217	48	487	2020/9/23
197	99	pandas	11715	585	1288	46	351	2020/9/23
198	99	matplotlib	11542	692	1269	11	230	2020/9/23

一天内会有多名用户进入订阅号,而一个用户一天内可能阅读了多篇文章
比如2020/9/21这一天,其中3名用户的阅读轨迹如下图所示。同一个用户在同一天阅读的所有文章我记做 1 次阅读,如此,我就有了以下 3 条阅读记录(事务)。

我们分析的是文章类型之间的联系,而不是单篇文章的数量关系,因此,尽管编号为74的用户同时看了2篇Python,这里也只记做1个。
综上,初步判断这份数据是可以达成总目标的,但不能直接进行关联分析,需要对数据进一步处理。
我们的第一个分目标是:获取可以直接进行关联分析的用户数据。

三、数据处理

目标 1:获取可以进行关联分析的用户数据,基于这个分目标,我们需要先对原数据进行处理,而处理这一环节,由两个步骤组成:数据清洗和数据整理。

3.1关于数据清洗,略… 3.2数据整理

前面,经过我们对目标的探讨,可以直接进行关联分析的数据,理想状态应该是长这样的:

处理这份数据的关键在于:① 提取数据 ② 数据去重 ③数据转换(列表) ④分组聚合
汇集同一个用户阅读的文章类型,也就是数据的合并,可能会联想到用sum()函数,将“文章类型”列进行求和,字符串就会“拼接”起来,像这样:

In [ 39 ]
1 test1 = pd.Dataframe({'班级': [1, 2, 2, 1], '姓名': ['王薇', '刘敏', '陈芳', '袁芬']})
2 test1 = test1.groupby(['班级']).sum()
3 test1
运行
Out [ 39 ]
姓名
班级	
1	王薇袁芬
2	刘敏陈芳

数据确实是“并”在一起了,但字符串首尾相连,连个空格都没有,后续不好处理。
问题似乎出在数据的格式上,既然字符串在聚合时会无缝拼接,不如先转换成列表,再来合并。

In [ 40 ]
1 test2 = pd.Dataframe({'班级': [1, 2, 2, 1], '姓名': [['王薇'], ['刘敏'], ['陈芳'], ['袁芬']]})
2 test2 = test2.groupby(['班级']).sum()
3 test2
运行
Out [ 40 ]
姓名
班级	
1	[王薇, 袁芬]
2	[刘敏, 陈芳]

怎么把字符串数据转换成列表,

第一步:提取列数据

In [ 41 ]
1
# 提取列数据('用户编号', '文章类别', '访问日期'),并进行赋值
2
user_data = user_data[['用户编号','文章类别','访问日期']]
3
# 查看提取的数据
4
user_data
运行
Out [ 41 ]
用户编号	文章类别	访问日期
0	1	数据分析	2020/9/21
1	2	数据分析	2020/9/17
2	3	数据分析	2020/9/2
3	4	数据分析	2020/9/24
4	5	数据分析	2020/9/8
...	...	...	...
194	98	pandas	2020/9/20
195	98	pandas	2020/9/20
196	99	数据分析	2020/9/23
197	99	pandas	2020/9/23
198	99	matplotlib	2020/9/23
199 rows × 3 columns

第二步:数据去重
同一时间内,一个用户阅读同类型的文章只能记作一次。

# 查看提取数据后的重复数据
analysis_data[analysis_data.duplicated()]
# 去除重复数据
analysis_data = analysis_data.drop_duplicates()

第三步:批量转换数据类型

In [ 178 ]
1
# 定义“格式转换”函数
2
def conversion_data(category):
3
​
4
    # 判断文章类别是否已经转成了列表格式
5
    if str(category)[0] == '[':
6
        # 直接返回文章类别
7
        return category
8
    # 返回转成列表格式后的文章类别
9
    return [category]
10
​
11
​
12
# 获取'文章类别'列,调用 agg() 方法
13
analysis_data['文章类别'] = analysis_data['文章类别'].agg(conversion_data)
14
# 查看处理后的数据
15
analysis_data
运行
Out [ 178 ]
用户编号	文章类别	访问日期
0	1	[数据分析]	2020/9/21
1	2	[数据分析]	2020/9/17
2	3	[数据分析]	2020/9/2
3	4	[数据分析]	2020/9/24
4	5	[数据分析]	2020/9/8
...	...	...	...
193	98	[数据分析]	2020/9/20
194	98	[pandas]	2020/9/20
196	99	[数据分析]	2020/9/23
197	99	[pandas]	2020/9/23
198	99	[matplotlib]	2020/9/23
192 rows × 3 columns

第四步:分组聚合

In [ 179 ]
1 # 根据'访问日期'和'用户编号'进行分组,并聚合'文章类别'列
2 analysis_data = analysis_data.groupby(['访问日期','用户编号']).sum()
3 # 查看整理后的数据
4 analysis_data
运行


这一步,要注意分组条件,既然是对同一访问日期下,相同的用户编号进行聚合,访问日期和用户编号就都是分组的条件

四、数据分析

在这里,我们要完成两个分目标,1.确认初始的最小支持度和最小置信度。2.确定最小支持度,最小置信度

如果想根据过往的经验设置最小支持度和最小置信度,那么,很遗憾,这是一个全新的项目,没有“作业”可抄。不妨尝试从业务和数据本身出发,寻找些“蛛丝马迹”。

观察处理过后的数据可知,抽样数据的访问日期均来自于2020 年的 9 月,用户总数和事务总数都为99。假设对访问频繁的文章组合的要求是,至少三天被访问一次。9 月有 30 天,事件发生的概率是:30/3/99 ≈ 0.1,由此,暂定最小支持度为0.1。
至于最小置信度,目前还没有啥头绪,不如先根据apriori()函数的默认值,也就是0.0,先筛选出一波数据,根据结果再做判断。

目标 3:调用 apriori() 函数,获取强关联规则

          apriori()函数用法

In [ 185 ]
1 # 执行Apriori 算法
2 results = apriori(adjusted_data['文章类别'], min_support=0.1, min_confidence=0.3)
3
​4
# 创建列表
5 extract_result = []
6
​
7 for result in results:
8
    # 获取支持度,并保留3位小数
9
    support = round(result.support, 3)
10
​
11
    # 遍历ordered_statistics对象
12
    for rule in result.ordered_statistics:
13
        # 获取前件和后件并转成列表
14
        head_set = list(rule.items_base)
15
        tail_set = list(rule.items_add)
16
​
17
        # 跳过前件为空的数据
18
        if head_set == []:
19
            continue
20
​
21
        # 将前件、后件拼接成关联规则的形式
22
        related_catogory = str(head_set)+'→'+str(tail_set)
23
​
24
        # 提取置信度,并保留3位小数
25
        confidence = round(rule.confidence, 3)
26
        # 提取提升度,并保留3位小数
27
        lift = round(rule.lift, 3)
28
​
29
        # 将提取的数据保存到提取列表中
30
        extract_result.append(
31
            [related_catogory, support, confidence, lift])
32
​
33
# 将数据转成 Dataframe 的形式
34
rules_data = pd.Dataframe(extract_result, columns=[
35
                            '关联规则', '支持度', '置信度', '提升度'])
36
​
37
# 将数据按照“支持度”排序
38
sorted_by_support = rules_data.sort_values(by='支持度')
39
​
40
# 查看排序后的数据
41
sorted_by_support
运行
Out [ 185 ]
关联规则	支持度	置信度	提升度
0	['sql']→['Python']	0.101	1.000	2.302
3	['Python']→['爬虫']	0.141	0.326	1.040
4	['爬虫']→['Python']	0.141	0.452	1.040
5	['pandas']→['数据分析']	0.182	1.000	1.222
6	['爬虫']→['数据分析']	0.192	0.613	0.749
1	['Python']→['数据分析']	0.323	0.744	0.910
2	['数据分析']→['Python']	0.323	0.395	0.910

关系是促进还是抑制,关键是要看它们的提升度。
本次筛选出来的强关联规则提升度大于 1(促进)和小于 1(抑制)的都有,但它们的指导作用是截然相反的,将数据分开来分析是一个明智的选择。

In [ 186 ]
1 # 提取出提升度大于1的数据,并重置数据的索引
2 promoted_rules = sorted_by_support[sorted_by_support['提升度'] > 1].reset_index(drop=True)
3 promoted_rules
运行
Out [ 186 ]
关联规则	                支持度	置信度	提升度
0	['sql']→['Python']	0.101	1.000	2.302
1	['Python']→['爬虫']	0.141	0.326	1.040
2	['爬虫']→['Python']	0.141	0.452	1.040
3	['pandas']→['数据分析']	0.182	1.000	1.222

有促进作用的关联规则一共有 4 个,其中“爬虫”和“Python”互为促进关系,阅读“sql”文章的用户更有可能阅读“Python”文章,喜欢阅读“pandas”文章的读者大概率也会喜欢阅读“数据分析”。

五、数据展现

查看数据的分布或者排序,一般会考虑使用柱状图来呈现。

5.1 绘制多组柱状图

这里需要绘制多组柱状图,重点在于规划好各组数据的 x 轴位置。而控制位置的方法,是调整plt.bar(x,height,width)语句的默认参数x。
参数x用于设置 x 轴的坐标,值为序列。如果参数x传入 df 的行索引作为 x 轴的坐标,柱形图的柱体会落在中间位置。

In [ 189 ]
1 import matplotlib.pyplot as plt
2 import warnings
3
​4
# 关闭警告显示
5 warnings.filterwarnings('ignore')
6
# 设置中文字体
7 plt.rcParams['font.family'] = ['Source Han Sans CN']
8
​9
# 创建df数据
10 hairs = pd.Dataframe([['许钢铁', 6, 5], ['王铁锤', 8, 7], ['林志龙', 9, 7]], columns=['姓名', '去年发量', '今年发量'])
11
​12 # 绘制基本柱状图
13 plt.bar(hairs.index, height=hairs['去年发量'], width=0.4)
运行
Out [ 189 ]



当对行索引进行加减运算,就可以改变坐标的位置,实现柱体的左右平移,注意观察代码,以及x轴坐标和柱体的位置。如下:
plt.bar(hairs.index-0.2, height=hairs[‘去年发量’], width=0.4)

柱体宽度为0.4,0.2刚好是柱体的一半,每个行索引值减去 0.2,相当于将柱状图整体向左边挪了半个体积。此时,再增加一组柱状图,以同一套行索引为基础,每个行索引值增加 0.2,向右边移动半个体积,将位置错开,再和前面的柱状图“组装”在一块,你就在一个图上绘制出了多组柱状图。

In [ 191 ]
1 # 设置柱体宽度
2 bar_width = 0.4
3
​4 # 使用两次 bar 函数画出两组条形图
5 plt.bar(hairs.index-bar_width/2, height=hairs['去年发量'], width=bar_width)
6 plt.bar(hairs.index+bar_width/2, height=hairs['今年发量'], width=bar_width)
7
8 # 纵坐标和横坐标标题
9 plt.ylabel('发量')  
10 plt.xlabel('姓名')
11 # 图形标题
12 plt.title('RY 工作室发量调查结果')
13 # 设置x轴的刻度名称
14 plt.xticks(hairs.index, hairs['姓名'])
运行
Out [ 191 ]

5.2案例展现

回到案例,前面提到,提升度不同,筛选出来的强关联规则含义不同,所以最好分开讨论。
实际上,由于提升度的取值范围和作用不同,有时候也会在绘制图表过程中,将它和支持度、置信度分开来看。
于是乎,我们将数据的可视化分成以下两部分:
1)根据提升度的作用绘制支持度和置信度的双组柱状图。
2)单独绘制所有强关联规则的提升度柱状图。

5.2.1紧接前面提取到含有促进关系(提升度大于 1)的强关联规则,我先来画一下它的支持度及置信度的双组柱状图。
In [ 192 ]
1 # 功能:绘制提升度大于 1 的强关联规则柱状图
2
​3
# 设置画布尺寸 
4 plt.figure(figsize=(20, 8))
5
​6 # 设置横纵坐标以及柱子的宽度
7 width = 0.2
8
​9
# 画出柱状图
10 plt.bar(promoted_rules.index-width/2, promoted_rules['支持度'], width=width)
11 plt.bar(promoted_rules.index+width/2, promoted_rules['置信度'], width=width)
12
​13
# 设置图例
14 plt.legend(['支持度', '置信度'], fontsize=20)
15# 设置标题
16 plt.title('促进关系的关联规则的支持度、置信度', fontsize=25)
17 # 设置刻度名称
18 plt.xticks(promoted_rules.index, promoted_rules['关联规则'], fontsize=15)
19 # 设置坐标轴标签
20 plt.xlabel('关联规则', fontsize=20)
21 plt.ylabel('数值', fontsize=20)

5.2.2绘制提升度小于 1 的关联规则柱状图。
In [ 194 ]
1
# 功能:绘制提升度小于 1 的强关联规则柱状图
2
​
3
# 设置画布尺寸
4
plt.figure(figsize=(20, 8))
5
​
6
# 画出柱状图
7
plt.bar(restricted_rules.index-width/2, restricted_rules['支持度'], width=width)
8
plt.bar(restricted_rules.index+width/2, restricted_rules['置信度'], width=width)
9
​
10
# 设置图例
11
plt.legend(['支持度', '置信度'], fontsize=20)
12
# 设置标题
13
plt.title('抑制关系的关联规则的支持度、置信度', fontsize=25)
14
# 设置刻度名称
15
plt.xticks(restricted_rules.index, restricted_rules['关联规则'], fontsize=15)
16
# 设置坐标轴标签
17
plt.xlabel('关联规则', fontsize=20)
18
plt.ylabel('数值', fontsize=20)

输出结果略…
基于这两份结果和公众号的排版需求,可以提出以下3条建议:
1)当“头条”文章是介绍有关“Python”的内容时,不妨考虑搭配“爬虫”的“次条”。
2)当“爬虫”类文章成为“头条”时,可以提高“Python”、降低“数据分析”的“次条”排布。
3)阅读“pandas”的用户大概率也喜欢“数据分析”,可在文章末尾,添加“数据分析”相关的拓展链接,提升阅读量。

5.2.3 绘制所有强关联规则的提升度柱状图:
In [ 196 ]
1
# 功能:绘制提升度柱状图
2
​
3
# 设置画布尺寸
4
plt.figure(figsize=(20, 8))
5
​
6
# 画出柱状图
7
plt.bar(sorted_by_support.index, sorted_by_support['提升度'], width=width)
8
# 设置标题
9
plt.title('提升度柱状图', fontsize=25)
10
# 设置刻度名称
11
plt.xticks(sorted_by_support.index, sorted_by_support['关联规则'], fontsize=15)
12
​
13
# 设置坐标轴标签
14
plt.xlabel('关联规则', fontsize=20)
15
plt.ylabel('提升度', fontsize=20)
16
​
17
# 设置数据标签
18
for a, b in zip(sorted_by_support.index, sorted_by_support['提升度']):
19
    plt.text(a, b, b, ha='center', va='bottom', fontsize=12)


可以看到,{Python}→{数据分析}、{数据分析}→{Python}的提升度都在 0.91 左右,接近于 1(无影响)。也就是说,喜欢阅读“数据分析”类的读者,可能在一定程度上影响“Python”的阅读量,反之亦然。具体情况,需要进一步分析,如扩大样本量或抽取其他的样本再次进行关联分析。

总结:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/286628.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号