专栏名称: PowerBI战友联盟
微软 Power BI MVP BI佐罗 带你学习BI真经。
目录
相关文章推荐
51好读  ›  专栏  ›  PowerBI战友联盟

99.9% 的人不知道的 PowerQuery 知识

PowerBI战友联盟  · 公众号  ·  · 2024-08-01 18:46

正文

请到「今天看啥」查看全文


Power Query 经常被描述为无代码或低代码数据处理工具,因为我们无需编写一行代码就可以在 Power Query 中对数据进行转换处理。只需单击鼠标即可选择许多功能,然后它们就会以近乎神奇的方式工作。



each



在我们点击鼠标的这个过程中,我们会在公式栏中反复看到的一个词是 each。

例如,在下图中,我们对地区列进行了一个筛选,选择地区列的值为东北的行。

each 出现了,这里 each 的作用是什么呢?为什么不直接是 [地区] = "东北" 。

我们来看一下官方文档对 each 的解释。

each 是一个关键字,用于轻松创建简单函数。“each ...”是采用 _ 参数“(_) => ...”的函数签名的语法糖。

语法糖是什么?_ 参数的函数签名是什么?还有,为什么简单地筛选  [地区] = "东北" 不使用 each 就不行呢?

我们以上面的筛选函数 Table.SelectRows() 为例,一起来看一下 each 它到底有什么用。

Table.SelectRows()  语法如下,第一个是表,第二个是函数。

例子如下,第一个是更改的类型表,第二个是 each ([地区] = "东北"),这里提出一个问题,([地区] = "东北") 是函数吗?

Table.SelectRows() 要求第二个参数是函数,而 ([地区] = "东北") 不是函数,是一个判断条件,它返回 True/False 布尔值,所以 each 在这里的作用是将 ([地区] = "东北") 变成一个函数吗?



M 中的函数



粗略地说,函数是一段可以重复执行的代码块。

函数通常具有一个或多个输入值(所谓的参数)。此外,函数还具有返回值(结果),一个简单的函数为:
(x, y) => x > y
我们在括号中定义函数的参数,上面例子中的 x 和 y。箭头 (=>) 之后是函数体,在函数体中确定返回值。在上面的例子中,返回值是一个数值布尔值。
在 M 中,很多情况下我们只需要处理一个参数。例如,如果我们想比较输入值是否大于 5。
(输入值) => 输入值 > 5
在这些情况下,我们可以用 _ 来代替来代表输入值表示唯一的参数,最终得到以下函数。
(_) => _ > 5
这就引出了语法糖,语法糖是在某些情况下对语法的简化。如果我们只处理一个参数,M 的语法允许我们选择不同的简化符号。
each _ > 5
这意味着,我们可以简单地省略函数箭头部分(括号及其内容),而直接使用 each 来访问隐式(单一)参数 _。
(输入值) => 输入值 > 5
(_) => _ > 5
each _ > 5
上述表达式都做着完全相同的事情:它们取一个数字,判断它是否大于 5,然后返回 true 或 false。
这有什么好处呢?在更复杂和嵌套的函数中,这种表示法可以显著提高代码的可读性。


引用操作符 []



Power Query 中的函数不仅可以接收数字或文本(字符串)作为参数。实际上,通过内置的 M 函数 Table.SelectRows(table as table, condition as function),我们可以看到整个表或一个函数都可以作为函数参数。
除了整个表,我们还经常需要处理行,这意味着我们经常需要以行作为参数的函数。
(行) => 对行进行某些操作
假设表中有一个单价列,因此每行都有一个名为单价的字段,我们希望将其增加 5 并返回结果。
我们如何访问行的字段?通过使用所谓的引用操作符:[ ],或更具体地说:行[列名]。
因此,我们的函数应如下所示:
(row) => row[单价] + 5
凭借我们在前面部分的知识,我们可以简化这个函数:
(_) => _[单价] + 5
好吧,让我们通过使用 each 进一步简化它:
each _[单价] + 5
现在,结合引用操作符,简化程度进一步提高。如果我们有一个参数,即一行,则可以使用引用符号 [] 直接访问此行中的字段。然后该函数如下所示。

each [单价] + 5



总结



Table.SelectRows() 函数需要表作为第一个参数的函数,即应该被筛选的表,然后函数逐行遍历该表。
对于每一行,Table.SelectRows() 执行第二个参数,即 Fuction 函数。该函数将当前行作为参数传递。因此,函数必须接受一行作为参数。最后,我们的函数必须包含一些搜索条件,如果找到则返回 true,否则返回 false。如果返回 false,Table.SelectRows() 将忽略当前行。如果结果为 true,该行将添加到新表中。这样,Table.SelectRows() 在处理所有行后最终返回一个新的筛选表。
那么我们的筛选函数应该是什么样子呢?
  • 参数必须是一行:(row) =>...

  • 在函数内部我们需要访问地区列: (row) => row[地区]
  • 函数的结果必须是一个布尔值: (row) => row[地区] = "东北"
  • 对于只有一个参数的函数,我们可以使用 _ 符号来简化: (_) => _[地区] = "东北"
  • 使用 _ 参数的函数可以用  each 进一步简化: each _[地区] = "东北"
  • 在 each 中使用引用操作符时可以省略下划线: each [地区] = "东北"

因此,最终结果是: Table.SelectRows(更改的类型, each [地区] = "东北")
Table.SelectRows() 采用步骤更改的类型中的表,并逐行遍历该表。对于每一行,它调用函数 each [地区] = "东北",将当前行作为参数传递,在该行中查找地区字段,并检查该字段中的值是否为东北。如果值是东北,函数将在当前行返回 true ,Table.SelectRows() 会将该行保留在筛选后的表中。如果值不是东北,函数将返回 false ,Table.SelectRows() 则不会在筛选后的表中显示该行。
现在,我们终于知道了 each 和 _  的含义以及 M 语言中的函数是什么样的!
只有掌握了 each 和 _ 的用法,我们在处理行数据时才会更加的得心应手。这里也问大家一个问题,如果相对一行进行操作应该怎么做呢?比如对一行的列名添加一个前缀,知道的小伙伴可以在留言区留言哦。

更专业的数据分析师训练营


🚀 《业财分析之道》 点击文字查看具体报名信息。

📈 《经营分析之道》 点击文字查看具体报名信息 。

🔍 数据分析之道 点击文字查看具体报名信息。
💡
商业智能之道 点击文字查看具体报名信息

🔗 如何获取更多信息?扫描下方二维码具体咨询。

BI佐罗数据分析 - 更专业更系统的企业数据分析

点击“阅读原文”获取更多资源







请到「今天看啥」查看全文