zoukankan      html  css  js  c++  java
  • Power BI Power Query 排名1-非连续排名和连续排名

    如下图所示,我有100个分数的数值,现需要对其进行排名处理。很久之前我有写过一篇有关Access里排名处理方式的博文Access SQL实现连续及不连续Rank排名,这一次我将其转换为使用Power Query来进行类似的排名操作。

    image

    非连续排名

    首先我们来实现非连续排名,非连续排名最终排出来的名次的数字是非连续的,假如第1名1人,第2名有2人,那么名次为3的人事不存在的,而只有从第4名开始。

    这种模式的计算逻辑是:对于某一个得分而言,其名次为大于当前分数的所有人的个数+1

    1、首先我们将Excel表数据导入到Power Query管理器中,选择表数据区域,然后依次点击“数据/从表格”,弹出的对话框直接点确认

    image image

    image

    2、接下来依次点击“添加列/自定义列”,我们首先借助于这个自定义列来为每一行获取一个子表,该子表包含了所有比当前行的分值大的所有行。

    在自定义列窗体中的配置如下图所示,其中的公式为:

    =Table.SelectRows(更改的类型,(r)=>r[分数]>[分数])

    image

    说明下公式:

    1、使用Table.SelectRows函数来挑选出表中的行

    2、Table.SelectRows函数的第1个参数:指明从哪个表里挑选数据,这个表是上一个步骤得到的结果,上一个步骤就是右侧查询设置步骤清单中的“更改的类型”

    3、Table.SelectRows函数的第2个参数:该参数是一个lambuda函数表达式,该函数表达式将会被逐行应用到Table.SelectRows函数的第1个参数表的每一行之上。

    (r) :这部分是lambuda函数的参数部分,其中的r是参数的名称,你可以使用任何字母,它表示的就是遍历参数表的行,你需要区分它与整个公式计算所在的当前行之间的差异。

            拿计算列的第1行为例,当前自定义列的公式所在的行是第1行,而这个lambuda函数将会遍历表的所有行,每次都取一行的值与当前行(第1行)的分数比较,我这里的表有100行,所比较操作就有100次;

            后面计算列的所有行都是相同处理,所以需要运算的次数为100*100=10000次。

    =>:箭头符号,用来分隔lambuda函数的参数部分和逻辑代码部分

    r[分数]>[分数]:lambuda函数的逻辑代码部分,该部分需要返回一个逻辑值,以便于Table.SelectRows函数判定是否需要挑选(筛选)出表中的行,返回结果为真时,表示挑选出来,否则过滤掉改行

           其中的r[分数]表示的取当前遍历行中的分数列的值,而大于符号后面的[分数]表示的是自定义列公式所处行中的分数列的值

    关于为何使用的是r[分数]来获取分数列的值,而不是使用r{[分数]}来访问这个值,是因为表(Table)中的行其数据类型是记录(Record),关于列表、表和记录数据类型及其访问子元素的方法我在Power BI Power Query 认识M语言中的结构性数据的博文里有说明,如果你不清楚,请先阅读下这篇文章。

    下图是添加自定义列“子表”之后的运行结果,我们可以点击第1行,底部就会加载该子表的数据

    image

    注意:不要点在哪个Table文字上,而是点在右侧空白区域里,点在文字上,PQ将会认为你是要新加一个步骤查看该子表的数据了

    接下来就需要将子表中的行统计一下,计算出总行数,并将该数字+1即可得出排名了,下面我们直接在前面的公式上修改

    1、在右侧找到最后的操作步骤,右侧有一个齿轮图表,点击一下它,就可以重新弹出“自定义列”对话框

    image

    2、输入如下所示的公式,点击确定按钮后,会看到如下面右侧图片所示的排名结果。

    =Table.RowCount(Table.SelectRows(更改的类型,(r)=>r[分数]>[分数]))+1

    image image 

    3、依次点击“主页/关闭并上载至”,依次选择“表/新建工作表”,点击加载按钮后,将我们的排名查询加载到Excel中,后续原始数据变动时,我们只需要刷新一下即可得到新的排名

    image image

    连续排名

    连续排名最终排序得到排名的名次是连续的,假如第1名1人,第2名有2人,那么接下来的名次并非从第4名开始,而是还是第3名。

    连续排名的逻辑:对于序列之中的某个分数而言,其名次是序列中大于该分数值的所有非重复分值的个数+1 

    之前的示例数据我是通过随机数方式生成的,制作本示例时,数据发生了变化,示例数据如下所示:

    image

    先说明下思路:

    借助于自定义列来为每一行获取一个子表,该子表包含了所有比当前行的分值大的所有分值的非重复记录。

    1、首先从表中挑选出比当前行分数大的所有记录行(与非连续排名一样)

    2、然后从上面第1步得到的表中再挑选出“分数”列

    3、再在上面第2步得到的“分数”列中取一个非重复值

    与前面进行非连续排名的操作类似,前面的导入数据操作步骤是一样的,所以这里我跳过这些步骤。直接演示上面所说的1-3步的实现

    1、新建自定义列,录入公式如下:(与非连续排名的公式一样)

    =Table.SelectRows(更改的类型,(r)=>r[分数]>[分数])

    image

    2、将公式修改为如下结果,公式输入完毕后,注意图中观察左下角子表的表现形式

    =Table.SelectColumns(Table.SelectRows(更改的类型,(r)=>r[分数]>[分数]),"分数")

    image

    说明下公式:

    1、首先我使用Table.SelectRows函数来过滤表中的行,得到分数大于当前分数的记录行,注意这些筛选后的记录行构成了一个新的表,它可以作为下一个Table.SelectColumns函数的参数

    2、然后再使用了Table.SelectColumns函数来从上一步过滤后的表中挑选出“分数”列

    3、Table.SelectColumns函数第1个参数:数据类型为表,函数将从该表中挑选出列来

    4、Table.SelectColumns函数第2个参数:当是字符串时,从表中提取出单列,当是列表是,从表中提取出多了,例如{“索引”,”分数”},表示从表中提取2列

    3、接下来继续改造公式,将公式修改为如下形式,其含义是在分数列上求一个非重复值,注意观察示意图左下角的分数列结果

    =Table.Distinct(Table.SelectColumns(Table.SelectRows(更改的类型,(r)=>r[分数]>[分数]),"分数"))

    image

    4、最后再在最外面套一个求行数的函数,并将结果+1即可得到连续排名的名次值

    =Table.RowCount(Table.Distinct(Table.SelectColumns(Table.SelectRows(更改的类型,(r)=>r[分数]>[分数]),"分数")))+1

    image

  • 相关阅读:
    Numpy基本介绍
    Java中的<< 和 >> 和 >>> 详细分析
    Matplotlib绘制基本图像
    Matplotlib基本使用
    最新动态:开源项目 ionic3-awesome — 实现生成带logo二维码组件
    最新动态:开源项目 ionic3-awesome — 实现iframe嵌入外部网页
    最新动态: 开源项目 ionic3-awesome — 实现多主题功能
    Angular5强势来袭
    js中对象的拷贝,浅拷贝和深拷贝
    vue2 + element-ui + axios 开源项目推荐
  • 原文地址:https://www.cnblogs.com/alexywt/p/11393638.html
Copyright © 2011-2022 走看看