数据可视化之DAX篇(二)Power BI中的度量值和计算列,你搞清楚了吗?
https://zhuanlan.zhihu.com/p/75462046
对于初学者,总是会把度量值和计算列搞混,我也经常碰到这样的问题,有些星友用文章中的代码总是报错,发给我一看,才知道TA把本来是度量值的DAX用在了计算列上,或者相反。
即使是已经学习了很长时间的人,对于计算列和度量值的写法也未必轻车熟路,还是有可能不明白其中到底有什么不同,这篇文章就试图把度量值和计算列彻底讲清楚。
什么是计算列、什么是度量值
计算列是直接在现有的表上添加一个新列,

新建的计算列,和表中之前已经存在的列一样,可以作为表格的行、列,图表的轴以及切片器的字段等等,也可以使用计算列与其他表建立关系。
而度量值,如果不放到上下文环境中,它就是一个孤立的公式,并没有视觉上的计算结果,因此,很多人会觉得度量值比较难以理解,尤其是Excel用习惯的人,都会倾向于使用计算列。
字段标识不同
如下图的字段面板

倒数第二个字段,前面有fx符号,代表的是计算列;而最下面一个,前面是个计算器的标识,表明[最后订单日期]是一个度量值。
怎么写计算列、怎么写度量值?
这个才是大家更关注的问题,也是平时容易出错的地方。下面以一个实例来介绍计算列与度量值的写法有什么不同。
以这个简化的订单表为例,如何计算出每个客户的最后下单时间?

计算列的写法
不少人也许直接这样写,

结果都是订单表中最后一个订单日期,显然与我们的期望不符,为什么会这样呢?
计算列的上下文就是当前行,但是MAX函数(包括SUM、MIN等聚合函数)并不能将行上下文转化为筛选上下文,也就是说当前行没有起到筛选作用,它就会返回整个表的最大订单日期。
关于上下文,不要理解的太复杂,完全可以按中文字面意思来理解,简单来说就是当前的计算环境,一般分为行上下文和筛选上下文,行上下文可以简单的理解为当前行,行上下文并不会必选产生筛选作用,只有筛选上下文才会产生筛选作用,筛选上下文有很多种形式,比如表格的当前行,矩阵的行和列、图表的坐标轴、报表的切片器、筛选器等。
如何让当前行发生筛选作用呢?在MAX函数外围再套个CALCULATE函数就可以了,

这样返回的下单日期都不同了,但是仔细看就会发现,返回的日期和当前行的下单日期是一样的,并没有按照客户进行计算。
再强调一遍,计算列的上下文就是当前行,包括当前行的每一个值,在上表中,每一行的数据是唯一的,因此只能返回当前行的订单日期。
那么到底如何按照客户来计算,返回当前客户的最后下单日期呢?
解决这个问题的DAX写法有很多种,这里用个相对简洁的代码,

ALLEXCEPT函数的意思是,清除订单表其他列的筛选作用,只保留客户列的筛选,这样当前行的上下文,其他列的筛选作用清除了,只有客户发生筛选作用。
比如客户甲,有两笔订单,使用MAX计算出最大的订单日期,也就是甲的最后下单日期。
上面说了这么多计算列的写法,那么度量值该怎么写呢?
最后下单日期=MAX('订单表'[订单日期])
是不是简单到不敢相信,那么如何看到计算结果呢,最简便的方式就是直接用个表格或者矩阵展现结果,
再举个例子,依然是这个订单表,如何计算每个产品的最后卖出日期?
如果你理解了上面计算列的原理,这个问题是不是也很容易就出来了,

那么度量值又是如何写才能解决这个问题的呢?
其实度量值的写法可以完全不变,依然可以用上面的代码(MAX('订单表'[订单日期]),只要把表格的维度改为产品名称就可以了,

通过上面两个问题,你看出来计算列和度量值有哪里不同了吗?
在计算列中,其上下文是明确的,就是当前行,并且可以根据需要缩小为当前行的某一列;
而度量值,编写时并没有明确的上下文,度量值写好之后,可以放在任意的上下文环境中,执行不同的计算;
计算列写好代码,数据自动计算出来,并且不受外部筛选器的影响;
而度量值写好之后,并没有立即计算,只有放到上下文中时,才进行计算并返回结果。
所以利用DAX解决问题时,首先应想到上下文是什么,新建列时如何利用当前行的上下文?
而度量值虽然暂时没有上下文,但在建度量值之前,也首先应该想清楚,我需要构建怎样的上下文环境才能得到期望的结果,然后利用心中所想的上下文环境,来对应的编写度量值的DAX代码。
在PowerBI中,除了计算列和度量值,还有个地方可以用到DAX,就是使用DAX新建表,

使用建表的方式同时可以解决上面的问题,

其中VALUES('订单表'[客户]),返回客户的不重复列表,就是为了给后面的代码提供上下文,有了这个上下文,后面的代码与新建列的写法是一样的。
通过这三种使用DAX的环境,以及上面的几个例子,应该能发现,无论是度量值、计算列还是建新表,其DAX代码本质上并没有什么不同,不同的只是下上文而已。
计算列只能利用当前行上下文;新建表可以使用DAX构建上下文;’而度量值最灵活,先不管上下文,写好代码之后,给什么上下文,就执行什么运算,或者说需要什么计算,就给度量值提供什么上下文。
你以后再遇到问题打算用DAX实现,一定要先想清楚,是通过计算列、新表还是度量值来解决,然后再开始写对应的DAX。
计算列和度量值写法的不同点
关于计算列和度量值在写法上有一些不同,比如在计算列中使用列,可以直接使用,默认就是该列的当前行,比如返回当前订单日期的前一天,可以直接写:

而在度量值中使用列,必须在列上套一个聚合函数,否则不能自动转换为筛选上下文,计算订单日期前一天的度量值应该这样写:
订单日期前一天 = MAX('订单表'[订单日期])-1

什么时候使用新建列,什么时候使用度量值
一般来说,为了性能考虑,能用度量值解决的问题就尽量不用计算列(参考:高效使用Power BI的15条建议)。只有当你需要利用新建的计算列生成切片器(度量值不能用于切片器),或者需要用这个字段与其他表建立关系时,才需要新建列。
另外当需要创建很复杂的字段时,尽量使用计算列,因为它需要时间来运算,提前运算完成,而不是在需要用的时候再进行计算(度量值是用的时候才计算),可以带来更流畅的体验。
总结
计算列和度量值在DAX代码的写法上并没有本质不同,形式上的不同只是由于上下文环境的区别引起的。
二者的本质不同在于其运算特点,是否根据上下文动态运算、以及计算时间上的不同,才是根本的差异。
如果你看到这里还是有不明白的地方,那么从头再仔细看一遍吧。
数据可视化之DAX篇(二)Power BI中的度量值和计算列,你搞清楚了吗?的更多相关文章
- 数据可视化之DAX篇(十一)Power BI度量值不能作为坐标轴?这个解决思路送给你
https://zhuanlan.zhihu.com/p/79522456 对于PowerBI使用者而言,经常碰到的一个问题是,想把度量值放到坐标轴上,却发现无法实现.尤其是初学者,更是习惯性的想这么 ...
- 数据可视化之DAX篇(二十七)半累加度量,在Power BI 中轻松处理
https://zhuanlan.zhihu.com/p/96823622 开始半累加的计算之前,我们先看看什么是累加.半累加以及不可累加数据. 在含有大量行的数据表中,各种数据处理语言,包括DAX ...
- 数据可视化之DAX篇(一)Power BI时间智能函数如何处理2月29日的?
https://zhuanlan.zhihu.com/p/109964336 今年是闰年,有星友问我,在Power BI中,2月29日的上年同期是怎么计算的? 这是个好问题,正好梳理一下,Power ...
- 数据可视化之DAX篇(十二)掌握时间智能函数,同比环比各种比,轻松搞定!
https://zhuanlan.zhihu.com/p/55841964 时间可以说是数据分析中最常用的独立变量,工作中也常常会遇到对时间数据的对比分析.假设要计算上年同期的销量,在PowerBI中 ...
- 数据可视化之DAX篇(五) 使用PowerBI的这两个函数,灵活计算各种占比
https://zhuanlan.zhihu.com/p/57861350 计算个体占总体的比例是一个很常见的分析方式,它很简单,就是两个数字相除,但是当需要计算的维度.总体的范围发生动态变化时,如何 ...
- 数据可视化之DAX篇(三) 认识DAX中的表函数和值函数
https://zhuanlan.zhihu.com/p/64421003 学习 DAX 的过程中,会遇到各种坑,刚开始甚至无法写出一个正确的度量值,总是提示错误.其实很多原因都是不理解 DAX 函数 ...
- 数据可视化之DAX篇(二十八)Power BI时间序列分析用到的度量值,一次全给你
https://zhuanlan.zhihu.com/p/88528732 在各种经营分析报告中,我们常常会看到YTD,YOY这样的统计指标,这样的数据计算并不难,尤其是在PowerBI中,因为有时间 ...
- 数据可视化之DAX篇(二十六)Power BI度量值:滚动聚合
https://zhuanlan.zhihu.com/p/85996745 上一篇文讲了累计聚合,这篇文章继续讲一下滚动聚合,比如常用的MAT计算,Moving Annual Total,滚动年度总计 ...
- 数据可视化之DAX篇(二十四)Power BI应用技巧:在总计行实现条件格式
https://zhuanlan.zhihu.com/p/98975646 如何将表格或者矩阵中值的条件格式也应用于总计行? 目前PowerBI并不支持这种功能,无法在总计行或者小计行上应用条件格式, ...
随机推荐
- Alink漫谈(七) : 如何划分训练数据集和测试数据集
Alink漫谈(七) : 如何划分训练数据集和测试数据集 目录 Alink漫谈(七) : 如何划分训练数据集和测试数据集 0x00 摘要 0x01 训练数据集和测试数据集 0x02 Alink示例代码 ...
- Bash知识点记录
变量的设置规则 1. 等号两边不能直接接空格符. 2. 右侧的变量内容若有空格符,可使用双引号或单引号将变量内容括起来,其中, 双引号内的特殊字符如 $ 等,可以保有原本的特性.如下所示: ...
- mysql常用基础指令大全
mysql指令 启动 net start mysql 退出mysql quit 登录 mysql -uroot -p 逻辑非 not ! 逻辑与 and && 或者 or || 逻辑异 ...
- Android学习笔记通过Toast显示消息提示框
显示消息提示框的步骤 这个很简单我就直接上代码了: Button show = (Button)findViewById(R.id.show); show.setOnClickListener(new ...
- Zookeeper——Watcher原理详解
文章目录 引言 正文 一.如何注册监听 二.如何触发监听事件 三.事件类型有哪些 四.Watcher可以被无限次触发么?为什么要这么设计? 五.Watcher实现原理 1. 客服端发送请求 a. 初始 ...
- Python学习手册(第4版) - 专业程序员的养成完整版PDF免费下载_百度云盘
Python学习手册(第4版) - 专业程序员的养成完整版PDF免费下载_百度云盘 提取码:g7v1 作者简介 作为全球Python培训界的领军人物,<Python学习手册:第4版>作者M ...
- Java Service Wrapper 浅谈
在实际开发过程中很多模块需要独立运行,他们并不会以web形式发布,传统的做法是将其压缩为jar包独立运行,这种形式简单易行也比较利于维护,但是 一旦服务器重启或出现异常时,程序往往无法自行修复或重启. ...
- 10、一个action中处理多个方法的调用第一种方法动态调用
我们新建一个用户的action package com.weiyuan.test; import com.opensymphony.xwork2.ActionSupport; /** * * 这里不用 ...
- Jenkins入门-环境搭建(1)-转
因为Jenkins的环境搭建比较简单,本来不想来介绍,但是发现有些入门小朋友,从各种网站上下载的各种安装包来搭建,最后导致出现了各种千奇百怪的问题,介于这种情况下我决定还是来写一下Jenkins的环境 ...
- java基础-java与c#接口不同点
1.接口中定义成员 C#,如图我在接口ITest添加了一个字段n,那么vs直接就显示红色的底线,而错误就是接口不能包含字段 java,如下图,编译也是报错但是并不是接口中不能包含而是缺少赋值,那么我们 ...