将 DAX 列转换为 power query(添加列)
Convert DAX column into power query (add column)
我有这个专栏,用于 scoring/ranking 销售的各种水果。它工作得很好,我正在进入一个更大的数据集,我想看看我是否可以将它直接移动到 power 查询中...
如何在'add column' in power 查询中编写代码? - 有可能吗?
普通列计算:
COLUMN NAME =
VAR NCT = TEST[Fruit]
VAR filteredTable = FILTER ( TEST, NOT ( ISBLANK ( TEST[Sold amount] ) ) && TEST[Fruit] = NCT)
RETURN
IF(ISBLANK(TEST[Sold amount]),BLANK(),
DIVIDE (
RANKX (
filteredTable,
TEST[Sold amount],
,
ASC
) - 1,
COUNTROWS ( filteredTable ) - 1
))*100
测试数据在这里:
https://www.dropbox.com/s/trrdggjz4c1x3ff/Test_scoringrank_in_powerquery.pbix?dl=0
我想我终于明白你在做什么了。
您不能通过添加自定义列来实现,但还有另一种方法。
Power Query 缺少 RANKX
函数,因此您必须编写自定义函数。
而不是每行的 FILTER
,在 PQ 中你会做一个 GroupBy
,然后在每个子组上执行自定义 RANK 函数。
您编写的 DAX RANKX
函数是一种 skipRank
类型的关系函数。还考虑到没有对 Sales Amount
为空白的条目进行排名。
对于自定义排名函数
- 每个 sub-group 升序
- 为每个金额分配一个序号(除非PQ中金额为空=null)
- 然后按金额对每个子组进行分组,并从中提取最低排名以获得并列排名。
- 展开表格。
其他步骤是内务处理。
希望我已经对代码进行了充分的注释,以便您能够理解。
自定义函数
- 添加为空白查询
- 重命名
fnScoringRank
(tbl as table, colToRank as text)=>
let
#"Sort by colRank" = Table.Sort(tbl,{colToRank,Order.Ascending}),
colRank = List.Buffer(Table.Column(#"Sort by colRank", colToRank)),
#"Add Rank Col" =
Table.FromColumns(
Table.ToColumns(#"Sort by colRank") &
{List.Accumulate(colRank,{}, (state,current)=>
if current=null then state & {null}
else if List.Max(state) = null then state & {0}
else state & {List.Max(state)+1})},
Table.ColumnNames(#"Sort by colRank") & {"Rank"}),
#"Group by colToRank" = Table.Group(#"Add Rank Col",{colToRank},{
{"all",each _, type table},
{"Scoring Rank", each List.Min([Rank])/(Table.RowCount(tbl)-1)*100, type number}
}),
//remove unneeded column and expand table
#"Remove Column" = Table.RemoveColumns(#"Group by colToRank",colToRank),
eXpand = Table.ExpandTableColumn(#"Remove Column","all",
List.RemoveMatchingItems(Table.ColumnNames(#"Sort by colRank"),{"Rank"})),
types = List.Zip({Table.ColumnNames(eXpand),{type text, type text, type text, Int64.Type, Int64.Type, type number}}),
typeIt = Table.TransformColumnTypes(eXpand, types)
in
typeIt
主查询
let
//Next two lines are from your code
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("XZBBD4IwDIX/y85cDDC8olET0EiyI+HQ6CILUEgRE/31bovG1cvW9Xvre1tdi3yaei0icTKd2/JlvpMBW8WiiWpxJsCbA+WIBFemSLmi8s0fzlLpBZUGsseuB+KClcffAKoFxBFttbcTL66VcINibBnm83cPYHfjECoz8NGxzJh7YQa7HjQNgE9brTP59zpYeqZIk9Bg25KZOZdMcDQvhpNP+m+AjdaEQO6H1QQGvYRHUMsMGHCZhgYlkAlpEluD5g0=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Fruit = _t, #"Account ID" = _t, Country = _t, #"Sold amount" = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Fruit", type text}, {"Account ID", type text}, {"Country", type text}, {"Sold amount", Int64.Type}}),
//Add index column to remember original order
#"Added Index" = Table.AddIndexColumn(#"Changed Type", "Orig Order", 0, 1, Int64.Type),
//Group by fruit
// Then run custom rank function on each sub-group
#"Grouped Rows" = Table.Group(#"Added Index", {"Fruit"}, {
{"Count", each fnScoringRank(_, "Sold amount")}}),
//Remove unneeded column and expand the table resulting from custom function
#"Removed Columns" = Table.RemoveColumns(#"Grouped Rows",{"Fruit"}),
#"Expanded Count" = Table.ExpandTableColumn(#"Removed Columns", "Count",
{"Fruit", "Account ID", "Country", "Sold amount", "Orig Order", "Scoring Rank"}),
//Sort back to original order
// Remove the sorting column
// Set the data types
#"Sorted Rows" = Table.Sort(#"Expanded Count",{{"Orig Order", Order.Ascending}}),
#"Removed Columns1" = Table.RemoveColumns(#"Sorted Rows",{"Orig Order"}),
#"Changed Type1" = Table.TransformColumnTypes(#"Removed Columns1",{{"Fruit", type text}, {"Account ID", type text}, {"Country", type text}, {"Sold amount", Int64.Type}, {"Scoring Rank", type number}})
in
#"Changed Type1"
来自您的数据的结果
我有这个专栏,用于 scoring/ranking 销售的各种水果。它工作得很好,我正在进入一个更大的数据集,我想看看我是否可以将它直接移动到 power 查询中...
如何在'add column' in power 查询中编写代码? - 有可能吗?
普通列计算:
COLUMN NAME =
VAR NCT = TEST[Fruit]
VAR filteredTable = FILTER ( TEST, NOT ( ISBLANK ( TEST[Sold amount] ) ) && TEST[Fruit] = NCT)
RETURN
IF(ISBLANK(TEST[Sold amount]),BLANK(),
DIVIDE (
RANKX (
filteredTable,
TEST[Sold amount],
,
ASC
) - 1,
COUNTROWS ( filteredTable ) - 1
))*100
测试数据在这里: https://www.dropbox.com/s/trrdggjz4c1x3ff/Test_scoringrank_in_powerquery.pbix?dl=0
我想我终于明白你在做什么了。
您不能通过添加自定义列来实现,但还有另一种方法。
Power Query 缺少 RANKX
函数,因此您必须编写自定义函数。
而不是每行的 FILTER
,在 PQ 中你会做一个 GroupBy
,然后在每个子组上执行自定义 RANK 函数。
您编写的 DAX RANKX
函数是一种 skipRank
类型的关系函数。还考虑到没有对 Sales Amount
为空白的条目进行排名。
对于自定义排名函数
- 每个 sub-group 升序
- 为每个金额分配一个序号(除非PQ中金额为空=null)
- 然后按金额对每个子组进行分组,并从中提取最低排名以获得并列排名。
- 展开表格。
其他步骤是内务处理。
希望我已经对代码进行了充分的注释,以便您能够理解。
自定义函数
- 添加为空白查询
- 重命名
fnScoringRank
(tbl as table, colToRank as text)=>
let
#"Sort by colRank" = Table.Sort(tbl,{colToRank,Order.Ascending}),
colRank = List.Buffer(Table.Column(#"Sort by colRank", colToRank)),
#"Add Rank Col" =
Table.FromColumns(
Table.ToColumns(#"Sort by colRank") &
{List.Accumulate(colRank,{}, (state,current)=>
if current=null then state & {null}
else if List.Max(state) = null then state & {0}
else state & {List.Max(state)+1})},
Table.ColumnNames(#"Sort by colRank") & {"Rank"}),
#"Group by colToRank" = Table.Group(#"Add Rank Col",{colToRank},{
{"all",each _, type table},
{"Scoring Rank", each List.Min([Rank])/(Table.RowCount(tbl)-1)*100, type number}
}),
//remove unneeded column and expand table
#"Remove Column" = Table.RemoveColumns(#"Group by colToRank",colToRank),
eXpand = Table.ExpandTableColumn(#"Remove Column","all",
List.RemoveMatchingItems(Table.ColumnNames(#"Sort by colRank"),{"Rank"})),
types = List.Zip({Table.ColumnNames(eXpand),{type text, type text, type text, Int64.Type, Int64.Type, type number}}),
typeIt = Table.TransformColumnTypes(eXpand, types)
in
typeIt
主查询
let
//Next two lines are from your code
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("XZBBD4IwDIX/y85cDDC8olET0EiyI+HQ6CILUEgRE/31bovG1cvW9Xvre1tdi3yaei0icTKd2/JlvpMBW8WiiWpxJsCbA+WIBFemSLmi8s0fzlLpBZUGsseuB+KClcffAKoFxBFttbcTL66VcINibBnm83cPYHfjECoz8NGxzJh7YQa7HjQNgE9brTP59zpYeqZIk9Bg25KZOZdMcDQvhpNP+m+AjdaEQO6H1QQGvYRHUMsMGHCZhgYlkAlpEluD5g0=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Fruit = _t, #"Account ID" = _t, Country = _t, #"Sold amount" = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Fruit", type text}, {"Account ID", type text}, {"Country", type text}, {"Sold amount", Int64.Type}}),
//Add index column to remember original order
#"Added Index" = Table.AddIndexColumn(#"Changed Type", "Orig Order", 0, 1, Int64.Type),
//Group by fruit
// Then run custom rank function on each sub-group
#"Grouped Rows" = Table.Group(#"Added Index", {"Fruit"}, {
{"Count", each fnScoringRank(_, "Sold amount")}}),
//Remove unneeded column and expand the table resulting from custom function
#"Removed Columns" = Table.RemoveColumns(#"Grouped Rows",{"Fruit"}),
#"Expanded Count" = Table.ExpandTableColumn(#"Removed Columns", "Count",
{"Fruit", "Account ID", "Country", "Sold amount", "Orig Order", "Scoring Rank"}),
//Sort back to original order
// Remove the sorting column
// Set the data types
#"Sorted Rows" = Table.Sort(#"Expanded Count",{{"Orig Order", Order.Ascending}}),
#"Removed Columns1" = Table.RemoveColumns(#"Sorted Rows",{"Orig Order"}),
#"Changed Type1" = Table.TransformColumnTypes(#"Removed Columns1",{{"Fruit", type text}, {"Account ID", type text}, {"Country", type text}, {"Sold amount", Int64.Type}, {"Scoring Rank", type number}})
in
#"Changed Type1"
来自您的数据的结果