何为详细级别
详细级别,英文 Level of detail,Tableau 用它来描述计算发生的级别,或者说计算在哪个层级发生。由于 BI 工具的相似性,在 Power BI 里也可以用类似的思想对计算进行描述,但 Power BI 并没有与之对应的专门的词汇。不过,理解详细级别对理解 Power BI 的计算仍然很有帮助,本文以 Power BI 为例介绍 Tableau 中的详细级别和详细级别表达式所传递的思想,理解它可以帮助你加深对 BI 工具计算过程的理解。
详细级别用来描述计算在哪个级别发生,最常见的两种详细级别是:
- Row Level of detail 行详细级别
- Visual Level of detail 视觉详细级别
行详细级别
行详细级别的计算发生在数据源所在表的每一行,并且不进行聚合运算。一个典型的行级别运算可以表示为下面的计算列:
Sales by row = SuperStore[Unit Price]*SuperStore[Quantity]
公式在 Superstore 的每一行计算单价和数量的乘积,得到每行的销售额,保存在一个新的列中。因为计算发生在最底层的明细级别,所以行详细级别的计算粒度最高,聚合度最低(没有聚合)。在 DAX 中,我们称之为受行上下文筛选的计算。
需要注意的是,并不是所有在计算列进行的运算都是行级别运算,比如这个公式:
Sum of Sales = SUM(SuperStore[Sales])
聚合函数 SUM 忽略行上下文,默认对整张表做聚合运算,所以公式得到的是所有销售额的总和。
视觉详细级别
将度量值或计算列拖入画布,视觉级别的计算就发生了。如果把上文定义的SuperStore[sales by row]计算列拖入画布,选择卡片图,结果显示为一个值。视觉详细级别的计算受所有维度筛选器的共同影响,因为本例中没有其他筛选器,所以它不受任何维度的影响,聚合度最高。
你可以向画布或黄色区域增加筛选器,这将改变视觉详细级别
将产品类别加入画布,修改图表类型为条形图,现在[sales by row]的视图详细级别变为产品类别,即,被来自产品类别的筛选上下文影响。
由于我们可以在画布中自由的对维度进行添加和组合,所以视觉详细级别可以有非常多的变化,从聚合度最高的单个值到明细级别,用一张图形象的表示:
可以看出,从金字塔的顶端到底端,不同的数据详细级别对应了不同的分析需求。看到这里,你可能会发现一个共性,这些分析都是可以直接通过拖拽的方式生成,这可以回答一些简单问题,但是无法解决稍微复杂一些的问题。
比如,按产品类别计算平均销售额很容易,如果我们要在当前视图中查看每个子类别的平均销售额并只显示出最大的那个,就不是那么容易了。原因是虽然图表显示的还是 By 类别的平均值,但发生计算的级别已经下降到了子类别粒度而不是默认的类别粒度。
或者,如果需要按薪酬区间统计人数,由于区间这个维度本身不包含在原始数据中,计算的详细级别也会发生变化。
想回答这类问题,DAX 给我们提供了一个很好的理论框架和一套函数作为工具,而 Tableau 借助的是图形用户界面和详细级别表达式(LOD Expression)
详细级别表达式
详细级别表达式从 Tableau 9.0 开始加入,在 Tableau 历史上这被视为一次里程碑式的更新。为什么详细级别表达式如此重要?因为它提供了这样一种可能性:允许用户在不修改视图(图表)的情况下,在计算中指定所需的详细级别,聚合度可以高于和低于当前视图使用的详细级别。也就是说你可以独立于图表所使用的详细级别,自定义另外一套详细级别来执行计算。
实现了这一功能,才真正打开了分析复杂问题的大门。以刚才的平均销售额为例,在没有详细级别表达式之前,必须向视图中加入子类别这个维度才能实现,而借助详细级别表达式,就可以将计算发生的级别定义在公式中。
详细级别表达式的关键字类型一共有三种: EXCLUDE、INCLUDE 和 FIXED,它们以不同的方式改变详细级别的计算范围。
Include: 以较低的详细级别进行计算
将计算级别指定为低于视觉级别的维度。上面的例子使用 Include 将平均值的计算从类别维度下移到了子类别。
Exclude: 以较高的详细级别进行计算
忽略指定的级别后进行聚合,一个典型场景是计算每个类别占总计的百分比,分母使用 Exclude 忽略类别筛选,始终返回总计值。
Fixed: 指定确切的详细级别
FIXED 参与的聚合运算只考虑所列出的维度,忽略其他条件。比如当需要从订单表中找出每个顾客的首次交易记录时,就需要使用 FIXED. 它可以明确定义计算发生的聚合级别。 与 INCLUDE 和 EXCLUDE 不同,该关键字可独立于可视化内容所用的维度之外来实现这一目标。FIXED 表达式结果的粒度可能会比可视化详细级别更低或更高,具体取决于 FIXED 维度和可视化详细级别之间的关系。
以上是关于 Tableau 详细级别表达式的简要介绍,想了解详细介绍可以参考 Tableau 的官方文档和白皮书,参考文献的链接在文章末尾列出。
互动有奖
各位读者,如果你是 Power BI 用户,文章到这里并没有结束,还有一个很重要的问题是:如何在 Power BI 中实现详细级别表达式这三个关键字的功能?
下面我们模拟一个最简单的情形,提出三个问题,请你用 DAX 给出解法,我会从全部答对的留言中选出回复最快的一位,获奖者可以从赠书列表中任选一本书或是一张可视化字典课程八折优惠券。中奖者身份确认以留言填写的邮箱为准,所以请填写真实邮箱地址。
基于 Orders 表定义如下三个 LOD 表达式,请用 DAX 给出对应的解:
- {EXCLUDE [Customer ID] : SUM([Sales])}
- {INCLUDE [Customer ID] : SUM([Sales])}
- {FIXED [Customer ID] : SUM([Sales])}
注:实际使用中,由于视觉维度的设定和 LOD 表达式所用列数的不同,以及多层 LOD 的嵌套,都会使问题更加复杂,各位可以自行探索也可以在文末留言交流,这里只用最简单的情况举例。
解决了这个问题,我们就可以开启下一道考验:在 Tableau 官网上,有这样一篇非常著名的博文,它从易到难介绍了基于详细级别表达式的15 个应用案例,这些案例涉及的场景和分析的思路都很有参考价值,并且最终的报告制作也十分用心。如果说详细级别表达式是皇冠,那 15 个案例就是皇冠上的明珠,下一篇文章我们一起来见证:
如何使用 Power BI 复刻 Tableau 15 大详细级别表达式案例
参考链接:
公布答案:
INCLUDE = SUMX(VALUES(Orders[Customer ID]),CALCULATE(SUM(Orders[Sales])))
EXCLUDE = CALCULATE(SUM(Orders[Sales]),ALLSELECTED(Orders[Customer ID]))
FIXED = CALCULATE(SUM(Orders[Sales]),ALLEXCEPT(Orders,Orders[Customer ID]))
恭喜西tomato红柿和DAVID获的赠书资格
请教大家,我如果要计算各月金额大于5000的ID数,用Tableau可以写成
SUM(IIF({INCLUDE[ID],[月份]:SUM([金额])}>5000,1,0))
用DAX可以写成
COUNTROWS(FILTER(SUMMARIZE(‘Sales’,[ID],[月份],”金额2″,SUM([金额])),[金额2]>5000))
问题是同样的数据量,Tableau算起来很快,DAX则非常慢。
这个DAX公式是不是还需要优化?
谢谢!
最近在学tableau的LOD。有点疑问咨询老师,仅仅针对tableau的FIXED函数,以文章中的字段为例,以tableau的超市数据作为数据源;
当在画布中出现与[Customer ID]不想关的字段时,比如再增加一个[区域]字段,DAX和LOD的处理结果不太一样。DAX的计算结果符合预期,而LOD需要额外增加指定为客户名称的筛选字段时,结果才符合预期。不知道是不是我理解有偏差,请老师指点下。(希望我表达清楚了。)
David 204
INCLUDE = SUMX(ALLSELECTED(Customers[CustomerID]),CALCULATE(SUM([Sales])))
EXCLUDE = CALCULATE(SUM([Sales]),ALLSELECTED(Customers[CustomerID]))
FIXED = CALCULATE(SUM([Sales]),ALLEXCEPT(‘Sales’,Customers[CustomerID]))
include是在筛选条件中增加values(),刚好看完15大详细级别
include,应该是内部迭代的意思,SUMX
结合前辈们的回答,我想挑战一下: included= CALCULATE(SUM([sales]),VALUES(‘customer[id]))
我好像知道included的意思了,是指定某个子类别计算好,方便直接用结果吗?
用earlier或者var:
var cus=customer[id]
return calculate(sum(sales),filter(表,customer[id])=cus))
Include:calculate(sum(sales)); 个人觉得直接放上去不就会按照条件自动筛选出结果了吗?
Esclued: calculate(sum(sales),allselected(customer[id]));
Fixed: calculate(sum(sales),allexcept(表,customer[id]))
EXCLUED忽略类别筛选,用ALLSELECTED,calculate(sum(sales),allselected(customer[id]));
FIXED只接受特定类别筛选,用ALLEXCEPT,calculate(sum(sales),allexcept(表,customer[id]));
INCLUED我没看懂,但我猜是用ALL,哈哈。。
SUM([sales])