在高级的分析中,大家会常见一个体现“二八定律”的帕累托图(Pareto chart),本质上是一种特殊的反映频率分布的直方图,这种分布具有明显的头部效应,这种现象在经济、社会等领域很常见。

面临非常多的数据,我们假设存在某种80/20的关系,即80%的数据是由占比20%的小群体贡献的,这个关系通常用一条向上拱起的弧线来表示,就像下面的这条线。更进一步,我们希望通过参考先获得准确的比例,甚至可以通过参数来控制百分比。

Screen Shot 2019-03-16 at 1.21.54 AM

1、直方图与帕累托图

直方图和帕累托图都是反映数据的分布,前者重在看分布的宏观态势,比如符合正态分布还是左偏、右偏?而帕累托图可以视为典型的左偏分布的升级版本,它通过查看累计数据的总计百分比告诉大家明确的头部市场的分布区间,典型的比率分析。我们可以详细比较一下二者的区别:

“直方图反映的是连续变量的概率分布”,比如不同年龄的员工分布,通常横轴是连续度量,纵轴代表分布情况,在Tableau中,连续度量通常使用数据桶(bin)转化为特定步长的连续区间,比如1-5岁,5-10岁,10-15岁等;标准的直方图像一个倒挂钟,符合典型的正态分布。

屏幕快照 2019-07-17 上午7.59.37

 

帕累托图更像是一条拱起的弧线,它的横轴和纵轴都是连续度量,并且通过转化为从0的1的百分位;不同于直方图的横轴是连续区间,纵轴是对应的数量,帕累托图横轴和纵轴都是代表百分位分布的连续度量。

更重要的是,帕累托图重在说明一个特殊的直方图情形——关键数据集中在左侧的(统计学上称之为左偏分布),即具有明显的“头部市场”的分布,比如80%的财富集中在20%手中,80%的销售来自于20%的高价值顾客等等。

比如,我们假设超市销售中,80%的销售是由20%的核心会员共享的。如何验证这个假设呢?我们需要把上面的数据转化为图形,这个假设包含了一个度量和一个维度:

  • 维度:顾客customer
  • 度量:利润profit

仔细分析上面的话,其中包含的计算逻辑是:总计百分比,80%是全部利润的部分,20%则是全部顾客计数的部分。

有一个难点在于,这个总计百分比的背后,还有一个累计计算,为什么?注意看上面的弧线,它的刻度是从0到100%,它表达的是“当前数据点之前的利润合计”在所有利润的占比,A点的百分比是原点到A所有利润合计的总额占比,B点的百分比则是原点到B点所有利润合计的总额百分比,这样到了最后一个点,此前数据点的利润就等于全部数据,因此为100%。

这个累计计算在Tableau可以用表计算快速完成,就是running_total()函数,上面图形中每个点的百分比,用Tableau的函数表示,就是 % of running_total(sum([profits])) .

2、实现基本的帕累托样式

我们按照思维的习惯通过拖拽完成上面的基本帕累托图形,粗略地验证是不是“大部分的业绩是由小部分的顾客贡献的”。

既然我们要分析顾客占比和利润占比,直接通过双击顾客字段“顾客姓名”和“利润”添加到可视化视图中,Tableau会自动生成条形图,我们把条形图改为柱状图,标记样式改为线,而关键步骤在于两次表计算:汇总running_total 和总计百分比 。

为了对比利润的绝对值,我们再增加一个利润柱状图(行),并改为双轴显示,就会出现上面的图形。

Screen Shot 2019-03-15 at 2.17.22 PM.png

3、横轴维度百分比化

上面的步骤相对简单,通过双重表计算实现“累计到当前数据点的利润合计占总利润的占比”,running_total实现累计计算,合计百分比percent of total实现绝对值的百分比化。

上面的图形可以大致看到有“头部效应”,但是难以精确的反映80%的销售对应的顾客占比是多少,因为横轴是离散的维度,而不是可以直接数字化的度量。使用Tableau做帕累托图形,难点在于如何把横轴的离散维度也变为百分比,同时还能保持上面的数据结构——说实话,我尝试了几十次,才找到了最方便的方法。

在上面的基础上,我们先假象维度字段改为百分比后的效果,假设总共有100个顾客,原点从0到100%,第20为顾客在20%的百分位上,第80位顾客在80%的百分位上。因此我们需要做两件事情:第一是把每个顾客标记为1,第二是标记它的位置,即位次除以总数量。

这里最容易出错的是,当我们把顾客计数后,视图出错了,因为之前可用的顾客字段消失了,但是我们的数据详细级别其实还是顾客,因此,我们要提前,或者出错后把顾客字段拖入到详细级别标记,保证数据详细级别不会变化。

逻辑和上面是一样的,区别在于维度先度量化,方法是使用计数函数,因为一个人可以购买过多次,但是我们计数一次,因此我们使用计数不同countd。这时,视图成了一条竖线,因为所有的顾客都计数为1,横轴只有一个数了。在维度数字化之后,如何计算自己所在的位置呢?每个顾客的计数都是1,那我是第几位顾客? 这里使用表计算–汇总。第20位顾客就会显示数字20,但是视图依然是一条竖线,还是1,为什么呢?因为默认计算依据是 表,我们需要改为特定维度——在顾客的维度上求汇总,这样第20位顾客,才会显示20.

Screen Shot 2019-03-15 at 2.50.29 PM.png

到这里,我们注意到横轴已经是数据点了,最后的800代表有800位顾客——这是我们的详细级别颗粒度。接下来,我们把绝对值位置改为百分位,和上面相同,在汇总表计算的基础上增加二次表计算,计算总计百分比,这样,坐标轴就改为了百分位,代表每个顾客在所有顾客中的位置。

帕累托 .jpg

到这里,已经接近终点了,不过我们注意到利润的弧线出了问题,我们修改一下表计算,计算依据改为特定维度(这里是顾客)。结果是这样的:

Screen Shot 2019-03-15 at 2.59.36 PM.png

为什么这里的弧线不像刚开始一样平滑?为什么利润柱形图如此混乱? 这是很多人容易迷茫的,问题很简单:此前默认的排序被打乱了,而顾客的排序默认是按照字母或者数据源次数的,我们希望它按照 度量值(这里是利润)的高低排序。很多人容易找不到排序的位置,这里藏在了“详细信息”的 维度那里——它决定了图形的详细级别和颗粒度,也可以控制数据的排列先后。我们按照 利润 降序排序,这时终于出现了帕累托应有的样子 !

Screen Shot 2019-03-15 at 3.06.13 PM.png

添加参考线就变得容易了。

3、坐标轴百分位转化的简易方法

上面我们通过 维度计数+两次表计算,实现了顾客维度转化为百分位,我们看一下坐标轴,它的含义就是 每个顾客自己的位次除以总的顾客数量,和利润百分位不同的是,这里每个顾客都用1来表示。熟悉表计算的朋友知道,表计算有几个常见的函数,index表示索引,size代表数量,如果我们用索引代表每个顾客的位置,就减少了running_total的计算过程,而size这里就可以代表total汇总。

因此,上面的部分过程可以简化为一个函数:index() / size()

  • 把列中顾客字段拖到标记–“详细信息”;
  • 在列中输入 index() / size() ,计算依据改为 指定维度-顾客名称。利润也注意其计算依据。

帕累托 index方法.jpg

到了这一步,再修改一下 顾客的排序方式就可以了。

当然,这种方法适用于熟练使用表计算的朋友,刚上手的还是以第一种方法为主,可以加深对整个分析过程的认识。

4、帕累托图形的优化

最后我们就要在帕累托图形的基础上增加参考线,从而可以直观的看到每个点对应的横轴和纵轴百分位位置。

我们设置一个动态的参数,控制我们想要的百分比数值,比如创建一个 “%profits”的字段,在右侧纵轴上添加参考线,引用这个参数。

Screen Shot 2019-03-16 at 1.12.44 AM.png

这里的关键是如何生成纵轴参考线。首先,我们看横轴参考线已经和帕累托弧线有了一个交叉点,我们先区分交叉点左右的数据,使用if函数可以返回一个临时字段,用上/下,或者默认的true/ false代替,在此基础上,我们可以再借助if函数,返回某一侧的数据,这样再添加参考线。

帕累托 参考线.jpg我们新建一个“横轴参考线”,返回在交叉点以上的度量,这样我们可参考线的最小值来生成参考线。注意,视图中没有横轴参考线的度量,需要加入到标记-“详细信息”;另外很多人容易忽视的,必须是连续字段才能作为参考线使用,因此我们需要把默认的离散改为连续,至关重要!

Screen Shot 2019-03-16 at 1.19.48 AM.png

最终的结果可以是这个样子:

Screen Shot 2019-03-16 at 1.21.54 AM.png

5、帕累托图的注意事项

  • 务必注意表计算的计算依据,这是最容易出错的地方;
  • 务必视图中显性引用的维度字段和参考线字段加入标记,同时修改计算依据;
  • 只有连续字段才能被参考线参数引用,务必务必。

 

「平民数据科学家」成长系列,希望通过方法论和思维方式帮助Tableau粉丝。

 

by 喜乐君

Tableau Partner ,Desktop and Server QA Certification

Mar 15, 2019
Aug 2, 2019 update “详细级别”改为“详细信息”,此前的笔误。增加直方图说明图。