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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM