Power Query M - 使用自定义聚合(百分位)按列值分组

Posted

技术标签:

【中文标题】Power Query M - 使用自定义聚合(百分位)按列值分组【英文标题】:Power Query M - Group by Column Value with Custom Aggregation (Percentile) 【发布时间】:2021-12-28 20:18:41 【问题描述】:

我正在尝试在电源查询中按组计算百分位数(从列值,例如:按部门的小时数、按地区的销售额等)。相同的逻辑可用于其他自定义组聚合。经过大量搜索,我找到了两种可能的方法。

方法一:

this archived article 看起来有完美的答案。我找不到其他任何东西。

那里的解决方案是以下自定义函数:

//PercentileInclusive Function
(inputSeries as list, percentile as number) =>
let
    SeriesCount = List.Count(inputSeries),
    PercentileRank = percentile * (SeriesCount - 1) + 1, //percentile value between 0 and 1
    PercentileRankRoundedUp = Number.RoundUp(PercentileRank),
    PercentileRankRoundedDown = Number.RoundDown(PercentileRank),
    Percentile1 = List.Max(List.MinN(inputSeries, PercentileRankRoundedDown)),
    Percentile2 = List.Max(List.MinN(inputSeries, PercentileRankRoundedUp)),
    PercentileInclusive = Percentile1 + (Percentile2 - Percentile1) * (PercentileRank - PercentileRankRoundedDown)
in
    PercentileInclusive 

结合表格中的一个步骤进行适当的分组并使用该功能:

=Table.Group(TableName, "Grouping Column", "New Column name", each
    PercentileInclusive(TableName[Column to calculate Percentile of], percentile # between 0 and 1))

[编辑以纠正 Ron R. 指出的错字并删除不必要的细节]

示例输入:

Pen Type Units Sold
Ball-Point 6,109
Ball-Point 3,085
Ball-Point 1,970
Ball-Point 8,190
Ball-Point 6,006
Ball-Point 2,671
Ball-Point 6,875
Roller 778
Roller 9,329
Roller 7,781
Roller 4,182
Roller 2,016
Roller 5,785
Roller 1,411

按笔类型分组的 25%(含 25%)百分位数的所需输出:

Pen Type 0.25 Inclusive Percentile (Correct)
Ball-Point 2,878
Roller 1,714

注意:上面没有显示小数,使用 Excel 的 PERCENTILE.INC 函数计算。

方法 1 效果很好。

方法二: 这是我尝试过的另一种 Power Query 解决方案。这是一个没有自定义功能的单一步骤。似乎它应该可以解决问题,但我想不出一种方法来使条件检查基于行。有些东西需要去我有 //Condition// 的地方告诉它哪些行属于当前行组,但无论我尝试什么它都不起作用。它要么中断,要么给出所有内容的百分位数,忽略分组。

=List.Percentile(Table.Column(Table.SelectRows(#"Previous Step Name", //Condition//), "Column to calculate percentile of"), percentile # 0 to 1)

任何想法如何使方法 2 起作用?

【问题讨论】:

如果您编辑您的问题以提供您的数据(或代表性数据)示例(作为可以复制/粘贴的文本)带有 那个 数据的所需输出的屏幕截图,以及用于获得这些结果的逻辑,这将有助于帮助您。 【参考方案1】:

看来您的Table.Group 函数指定不正确。

我之前的步骤是#"Changed Type",以下工作:

    #"Grouped Rows" = Table.Group(#"Changed Type", "Pen Type", 
        "Percentile", each fnPercentileINC([Units Sold],0.25))

原始数据

M 码

let
    Source = Excel.CurrentWorkbook()[Name="Table4"][Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,"Pen Type", type text, "Units Sold", Int64.Type),
    #"Grouped Rows" = Table.Group(#"Changed Type", "Pen Type", 
        "Percentile", each fnPercentileINC([Units Sold],0.25), type number)
in
    #"Grouped Rows"

结果

编辑: 对于您的方法 #2,没有自定义函数,您只能使用 List.Percentile 作为 Table.Group 函数中的聚合:

   #"Grouped Rows" = Table.Group(#"Changed Type", "Pen Type", 
        "25th Percentile", each List.Percentile([Units Sold],0.25)       
        )

【讨论】:

感谢您的仔细检查。这确实是我每次检查自己时都会犯的一个愚蠢的错字。我将清理原始问题以供将来参考。关于如何使方法 #2 起作用的任何想法? @plasmas222 查看我的编辑。只需在Table.Group 聚合中直接使用List.Percentile 太棒了,谢谢。对于引用此内容的任何人,如果已经有内置函数,请使用第二种方法,并在需要自定义函数时使用第一种方法。

以上是关于Power Query M - 使用自定义聚合(百分位)按列值分组的主要内容,如果未能解决你的问题,请参考以下文章

使用 plsql 的用户定义的自定义聚合函数

使用 jOOQ 创建自定义聚合函数

Reporting Services 使用啥类型的对象将多行传递给自定义聚合函数?

60种特征工程操作:使用自定义聚合函数

python自定义聚合函数,merge与transform的区别

Power BI 中的 M(Power Query),将参数从列表传递到 SQL 语句