迭代过程iteration及迭代函数分类(上)

by 喜乐君 (敏捷BI)

在学习Power BI的DAX过程中,会发现很多常见于编程语言的概念,比如迭代iteration、赋值(var)、定义DEFINE等,这也是它不同于Tableau、SQL的关键特征——SQL中没有赋值和循环的处理,Tableau计算虽有参数但无显性的循环方法,Power BI既有参数(以数据表的形式出现),也有多种间接实现循环的方法(比如EALIER函数,虽然并不容易,但至少可操作)。

“SQL中没有赋值或者循环的处理,数据也不以记录为单位进行处理,而以集合为单位进行处理。SQL和关系数据库的思维方式更像是一种整体论的思维方式。”——SQL进阶教程

要完全理解DAX语法,理解DAX相对于SQL/Tableau在计算上的关键差异,就先要理解一些关键概念:迭代iterate、循环loop、遍历(traversal)、递归(recursion)等。它们既有差异,又相互联系,是计算背后接近算法的部分,是辅助理解复杂问题解决方案的关键概念。

本文的重点是迭代(iteration),这也是DAX“计算列”的关键。

先从最简单的计数来理解迭代(iteration)的过程,之后介绍迭代的分类及其组合形式,这是理解各种迭代器(iterator)函数的基础,比如SUM、SUMX和FILTER。

一、迭代iteration过程及其分类

何为迭代(iteration)?迭代既是程序设计中的关键概念,指程序设计中的重复计算,也被引用到社会科学领域,比如说管理理念或课程体系“迭代升级”。理解迭代的关键是重复,这种重复又不同于简单的循环,而是前后依赖的重复,直至最后一个值;同时,每次迭代,都要执行相同的程序计算。

在Power BI中,DAX作为近似编程语言的分析工具、函数式分析语言,也引入了程序设计的迭代概念,指按照指定顺序、逐个访问数据集中的每一项。分析中的“指定顺序”,可以默认理解为线性次序。

理解迭代的关键是“逐个访问“(one by one),也可以理解为重复(repetition)。

Iteration: repetition of a mathematical or computational procedure

这里以简单迭代(计数)辅助帮助理解迭代iteration的过程;而后介绍两类“迭代器”(iterator)和函数。

1、计数:自上而下、输出唯一值的业务分析

迭代其实就在我们身边,体育课出勤计数、老师收作业、定投基金,这些场景中都有迭代的影子。

举个形象的例子,体育课时很多人人站为一个队列,老师想要知道有多少人来上课了,就会让大家从头到尾、依次报数。报数自动止于最后一人,最后一人的报数,既是他在队列中的标记,也是队列的总人数。分析中,把这个过程称之为计数(COUNT)。

计数,可以说是最简单的迭代。迭代的关键是依次、访问整个队列。

我们既可以可视化地把多个人想象成为一个队列,也可以用数学的方法记作一个数据集。不管外在的展现形式如何,想要知道有多少人(多少个元素),必须依次、逐个标记数字,这个过程就是迭代数据集。

添加图片注释,不超过 140 字(可选)

对数据库中特定数据表的计数也是同理。区别在于,常见数据表是多行多列构成的关系结构(relational schema)。数据表的每一行是一个元组(tuple),元组中可以包含不同类型的多个数据值,比如(王五,10,0.4),换个方式理解,元组就是行(row),就是记录(record)。多个行构成了数据表。

对数据表的计数计算,就是计算有多少个元组。参考之前的逻辑,相当于逐行扫描数据表中的每一行(scan table row by row),然后标记1、2、3……的过程,扫描到最后一行对应的数字,就是数据表的行数。

添加图片注释,不超过 140 字(可选)

上述的两个过程,可以近似地比作数据分析中对字段计数,和对数据表行数计数的过程。产品经理和产品工程师把高频使用的分析功能,整合、封装为特定的函数,于是就有了如下的函数:

COUNT('table name'[客户数量])
COUNTROWS('table name')

在分析中,还有很多与之类似的迭代函数,最典型的比如SUM求和、AVERAGE算术平均、MAX最大值、MIN最小值等。站在迭代的角度看,这些函数就是生成迭代的“迭代器”(iterators);而从明细到抽象的计算角度看,这些函数都是由多变少的“聚合函数“(aggregation functions)。

从分析的角度看,此类迭代函数,即聚合函数,可以完成数据的抽象概括,因此又可以称之为分析函数。

2.日期计算:自左到右、输出数据表的数据准备

还有一种迭代计算,迭代过程也是自上而下、row by row,只是计算过程是自左到右,每一行的输出各不相同、相互独立。

比如,在数据表明细行,计算每一行订单日期对应的订单年度,在Excel或者Power BI中,都可以用YEAR函数计算而来。相比前面的计数函数最终只返回一个值,这里的YEAR则会返回很多值(理论上每一行都可以截然不同),单看输出结果,可以视为是一列多行的数据表。

添加图片注释,不超过 140 字(可选)

在数据分析过程中,几乎所有的数据准备工作,都是类似的计算逻辑。比如销售单价*销售数量、销售额*折扣率、发货日期-订单日期(发货间隔)、从产品名称中拆分「品牌」字段等等。

这些计算的共同特征是:(1)在数据表明细行中完成,每一行的计算完全独立、互不影响;(2)返回的结果是数据表,即多值。

从分析的角度看,此类计算可以称之为数据准备类计算(Data Preparing Calculations);与之相对的则是则是以计数、求和为代表的分析型计算(Analytical Calculations)。这不仅仅是迭代计算的分类方式,也是函数的分类方式,更是计算的分类方式。

此为业务视角。

3、Python中的迭代:聚合和逐行输出

在Python或者其他编程语言中,迭代属于常见功能,比如for、while都可以实现迭代。

使用for可以逐行打印一个列表(list)中的所有成员,这就是最简单的迭代输出。比如

for value in  ts_code:
     print(value)

如果翻译一下,上述过程就是:对于ts_code中的每个值,执行打印print输出。

我在查询公募基金数据时,常常使用这样的方法。如下的for循环,就会把ts-code中每一个数据值依次打印一遍,逐个访问,如果已经在数据库中存在,那么就会跳过,否则就会执行特定命令。

添加图片注释,不超过 140 字(可选)

上述的Print输出是列表中每个元素逐一输出(one by one),也可以在这个过程中,增加聚合计算过程。比如计算列表中总共又多少个数据表(类似于分析中的COUNT函数)。 为此,只需要在for的迭代过程中增加一个累加计数器就好,如下所示:

#  iteration 
j=0 
for i in range [list]:
     print(i)
     j=j+1
     print(j)

在这里,提前定义了一个变量j,它会随着队列的逐行输出加1(j=j+1),最后输出的数字,就是整个队列的数量,即计数。而每一个元素都会输出一个值,可以视为是元素的编码;和体育课依次报数一样。

当然,和分析工具中一样,Python的工程师把计数这种简单、高频应用,封装为特定的功能,于是就有了shape,len等函数,以及pandas中的agg函数。

import numpy as np 
Df.groupby("species").size() 
Df.groupby("species").agg(["max",range_flowers])

可见,在Python中,迭代过程也可以分为逐一输出、逐一相加两种基本样式。迭代过程完全相同,差别只在于计算逻辑。

4、小结:迭代计算的两种类型

从上述的多个场景中,我们可以做出如下的总结:

  • 迭代函数的共性是逐行访问数据表(即多个元组)的迭代过程(iterate the table row by row);
  • 迭代的列表或数据表是迭代对象,这是迭代计算的基础;
  • 迭代对象的迭代次序,可以默认理解为都是线性的;在计算引擎中,也可能会有优化方案,比如排序时的二叉树方法,这些不属于应用层面控制的内容,可以忽略。
  • 迭代函数的差异,体现在与迭代过程相结合的计算和返回值上:
  • 部分迭代计算只返回一个唯一值,称之为标量值(scalar value),比如COUNT计数函数、Python的len函数等
  • 有些则是逐行计算、按条件输出,返回很多值构成数据表(table),比如Python中的Print输出,或者DAX的filter函数

为了方便理解不同迭代器的差异,可以把迭代函数、迭代器拆分为迭代对象、迭代计算两个部分。二者紧密结合,又相互独立,多个迭代函数的迭代对象可以是完全相同的,但区别在于计算不同、输出不同。

  • 迭代的对象可以是列表,也可以是数据表。而迭代次序默认是线性地逐个访问,对于列表LIST而言就是“逐一”one by one,对于数据表TABLE而言,就是“逐行”row by row 。直至迭代完整个迭代对象。
  • 迭代计算,就是在每个迭代元素处、执行的计算过程,可以形象的理解为“自上而下”和“自左到右”两种计算过程。它们对应两种迭代类型,如下所示:
添加图片注释,不超过 140 字(可选)

在Python中,典型的两类迭代函数是Len长度计算和Print打印,前者返回单一值,后者返回多个值。

在DAX中,典型的两类迭代函数是SUMX迭代求和,和FILTER迭代过滤函数,前者返回单一值,后者返回数据表。前者的重点是聚合,后者的终点是过滤;前者是结构上的变化,后者是数量上的变化。

💡聚合一定包含迭代过程,但迭代不一定是聚合计算。

POWER BI中,FILTER可以理解为for或者while判断,它扫描数据表、逐行判断筛选条件(filter condition),然后返回符合条件的数据表明细行,因此结果还是一个数据表。这里可以用列表来表示:

#  iteration 
for i in range(10): 
# print(i)
     if i > 5:
     print(i)

V1 Jan 9, 2023 喜乐君 V2 Jan 14, 2023 增加排序等 V3 Jan 18, 2023 V4 Jan 30, 2023 修改第一部分,发布知乎

发布者:喜乐君

喜乐君 | Tableau Partner,Tableau Desktop and Server QA Certification

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

您正在使用您的 WordPress.com 账号评论。 注销 /  更改 )

Twitter picture

您正在使用您的 Twitter 账号评论。 注销 /  更改 )

Facebook photo

您正在使用您的 Facebook 账号评论。 注销 /  更改 )

Connecting to %s

%d 博主赞过: