前段时间,抽时间基于BigQuery+Python+ECharts实现了一个无抽样自定义行为流报告。
本来想着介绍一下这个东西的价值,无抽样啊~强大的可视化功能啊~广阔的高定制延伸空间啥的,结果手放到键盘上,在和键盘僵持了数小时后,我决定还是放弃了。
手里拿着锤子,看什么都像是钉子,为什么非要为锤子找一个存在的价值呢?做锤子本身不是也蛮有趣的吗?
对吧对吧,ok~所以我们就不赘述无关内容了。
下面我们详细的看下这个小东西最终实现的效果(涉及的相关数据&信息,都是用的虚拟数据,大家仅做参考)。
可以看到,工具的使用,由如下步骤组成:
1)点击**.bat(这是一个批处理文件,内置了一些命令,用于调用Python的脚本,以加载呈现后续的GUI)
2)弹出窗口,进行选项的配置,包括(来源数量限制、目标数量限制、层级限制、数据拉取的开始日期、结束日期、BigQuery身份验证文件、BQ项目ID、数据集ID)
3)开始查询,查询结果自动弹出加载,呈现为桑基图+饼图的形式,桑基图表现了入站用户浏览网页的流向,饼图呈现了某个节点流出的目标。
实现架构
这个工具的实现架构很简单,其中应用的核心技术为:BigQuery+Python+ECharts
BigQuery:负责行为流所需数据的查询;
Python:
- tkinter:负责GUI页面呈现、相关参数的获取&传递
- google.cloud.bigquery:负责用户身份的认证&BQ JOB的调用&BQ查询结果数据的获取
- pandas:负责BQ查询结果数据的相关处理
……
ECharts:负责数据的可视化,主要包括桑基图、饼图
这其中,最核心的是BigQuery,没有BQ我们无从查询获取原始数据,而除了BigQuery外,其他的技术都可以替换,事实上,比当前搭配更优的方案甚多,围绕Python,GUI上除了Tkinter外,还可以考虑使用PyQt/pyglet/wxPython/Toga。
如果想采用网页形式,则可以使用Django或Flask,采用网页进行参数的填写&可视化结果的呈现(事实上这确实是一种蛮优的方案),ECharts做可视化呈现效果很好,但此外还可以使用,例如Matplotlib(Python库)/Google Charts等。
如果不使用Python,那么JAVA/R/node.js等也都可以完成搭建工作,尤其是使用 node.js结合Electron,可以搭建一个非常优质的桌面应用。
方案很多,那为什么选用当前方案呢?
简单。
首先Python&Python-Pandas就不必说,普及程度很高了,而Tkinter是Pyhon的原生GUI标准库,安装了Python就能用。
ECharts是一款开源的前端可视化库,功能丰富,文档齐全,深受业界好评,而且 Demo甚多,与Python也有开源的PyECharts可以使用,非常方便。
技术原理
依赖于例如ECharts的可视化库,我们在技术上的核心,即在于“如何拉取合适的数据”。
以桑基图为例,下图为官方提供的一个简易的图表示例:
那么这个简易的图表需要什么样的数据呢?
有两部分组成,一部分为所需呈现的节点(名称),表现为如下形式:
另一部分,则为各节点间的关系,如下图所示:
即“流量”从哪个节点出发,去往哪个节点,量有多大。而当灌入了数据后,图表就会自动进行构建,自动渲染出如上的图样。
当然,由于我们没有进行其他的设置,上述的图例采用了大量默认的配置,但如果我们需要,就可以进行诸多自定义的内容。
但这个时候,可能也会有朋友发现问题,在GA行为流报告中,数据除了节点、流量、流向外,还存在层级的划分,而上述数据中,却没有显性的设置节点,那么我如何确保从网页A进入网页B再进入网页B这个过程,被准确的识别呢?
(截图自GA DEMO账户)
仍以示例数据为例,如果我们把a/b/c分别看做网页,把a1/a2看做层级,其实就好理解了。
在ECharts中,桑基图表现为一种有向无环图(DAG),节点间的流动关系,自动串联出了层级关系。
以用户A-B-A的浏览为例,则对应数据为:
即A-B-A2。
这里的A/A2实质是一个网页,只是被划分为了不同层级下的不同节点。
基于这个简单的数据示例,我们就可以继续延伸,归纳所需的数据架构,以GA用户行为流图为例,则要知道对于用户来说:
用户此时正处于第几步(在看第一个网页、还是第二个、或者是第十个?)
用户此步浏览的网页(这里以网页为例,也可以是事件、屏幕浏览、屏幕+事件等等,随意)是什么、从这个网页后用户又去了哪些网页(也可能流失了)。
然后再对这些数据加以聚合、统计,得到我们最终所需的数据。
如下图所示:
可以看到,开始的时候,我们获取每个用户的浏览路径,然后将浏览路径拆分为从哪里来到哪里去的结构,并标注层级。
接着,我们在by节点对数据进行聚合,得到从某个层级下某节点流入到其他节点的数据总量。
BQ实现
确定了所需的数据结构&数据构建逻辑,接着就需要编写相应的BQ查询语句以实现。
在BQ中,GA的底层数据,按照每个会话为一行的形式存储,而一个用户的会话中,又可能嵌套着数个Hits,同时这些Hits被诸多列维度所定义。
例如下图所示:
(BQ GA导出部分字段)
Hits表示一个匹配(或者说命中),通常我们在网站上所触发的一次网页浏览、一个事件,都是一个Hits。
Hits有多种类型,由Hits.type定义,例如:PAGE/EVENT/APPVIEW等等。
如果想要单独看PAGE即网页浏览类型的匹配,则我们即可通过筛选hits.type= ‘PAGE’的匹配。
找到了用户浏览的网页,那如何定位这个用户浏览的下一个网页呢?
在这里,我们使用hits.hitNumber来确定:
筛选出hits.type为PAGE的匹配,然后再根据hits.hitNumber来进行排序,就可以获取到节点的先后顺序。
当然由于这个参数是by用户by会话的,那么为了识别唯一用户会话下的hits顺序,我们还需要fullVisitorId&visitNumber来进行界定分组。
节点&顺序都获取了,我们还需要将当前步&下一步抽取出来,此处有多种实现方案,最佳的方法是使用导航函数LEAD()
LEAD()函数用于返回后续行的值,结合LEAD()函数并使用fullVisitorId&visitNumber 进行分组,我们就可以获取到所需的值了。
得到这部分核心数据后,剩下的工作就是聚合COUNT/GOURP BY的问题,这部分很简单,就略过不提了。
(对于此处数据的查询处理,其实还有很丰富的工作可以做,比如我可以使用内容组来做节点、用事件、屏幕浏览做节点,对数据进行处理、替换、按照流量对节点进行归类,例如将节点过小的长尾部分,划分为Other等等。)
Python在这里的应用
我们在前文中有提到,Python在这里并不是不可替换的,使用的目的主要是简单,但是大部分技术原理都是共通的,这里简单描述一下Python的价值,以做参考。
对于BigQuery的使用,在日常工作中,往往是基于BQ的WEB UI界面的,如下图所示:
不可否认,其功能丰富、美观大方、确实好用。
但是我们不可能也不会希望,每次生成图表都需要自己手工去跑数据,然后再进行下载,这无疑太麻烦了,好在BQ提供了丰富的API与相关库,允许通过API的形式执行命令,获取数据。
google.cloud.bigquery就是官方针对Python提供库工具。其中就内置了诸如身份认证(你肯定得保证数据的安全吧,对吧)、数据查询、数据获取等方法。
数据获取到了,我们有时候还希望对数据进行一些变换、处理,这些操作可能在BQ 中执行不便,或代价较高,那就可以使用Python对数据进行二次处理(当然Python还挺擅长这些事情的)。
直接写代码执行这些操作当然是可行的,但我们肯定也不希望每次都需要开脚本,写代码,而且如果给不偏重技术的同事使用,那么他们的学习成本也显得不太合理,所以一个GUI界面,就比较必要。
在这里使用了Python内置的Tkinter,这个比较简单,而且替换方案非常多,略过。
一些延伸
基于上述的DEMO&逻辑,其实后续可以操作的空间、可以尝试的操作就很多了。
比如,我们现在采用的是固定时间的可视化呈现,那么可不可以根据连续的时间周期,做成动画形式呢?当然是可以的。
我们可不可以调整数据呈现的样式,比如流量上数据量级差异很大,能否先对数据做放缩,然后再渲染,在保留大致趋势的前提下,增加数据的可读性呢?肯定也是可以的。
再比如,我们现在针对的维度指标是不是可以丰富?
我们是不是依据现有数据,结合机器学习,对目标达成的数据流进行区分、辨别等等。
总之,当实现了这个小的DEMO后,你就拥有了一把“锤子”,那么无论接下来你是想找钉子,还是想把它做得更称心,亦或是想要从做锤子的过程中,感悟一些比èbai¾ƒè¾“入的é的原理,就都随你了。
以上希望对各位有所启发~