Table.Profile()

Table.Profile()可以抽象地概括为function(table as table, optional addtionalAggregates as nullable list) as table,大概的意思为:(1)该函数的第一个参数为需要列汇总的表格。(2)第二个参数的性质为可选的,当使用者没有填写第二个参数时,函数默认产生的列汇总为最小值,最大值,平均值,标准差,数字个数,空值个数以及唯一值个数,如果需要除此之外的列汇总,需要以{{}..{}}形式的复合串列填写第二个参数(本文所给出的填写方法来自Chris Webb的文章)。

本案例假设上表(DB)记录的每一个行业最多只有9间企业,该表的每一列记录了处于该行业的每一间公司的市场份额,现在要求基于每一列对应的HHI(市场份额平方之和)大小对表格进行分割,HHI大于0且小于等于1500的为一组,大于1500且小于等于2500为另外一组,剩下的列归类为一组。转换后的效果如下图:

以下为以Table.Profile为中心实现转换的代码:

let
    Profiling=
        Table.Profile(
            DB,
            {
                {
                    "HHI",
                    each Type.Is( _, type nullable number),
                    each
                        List.Sum(
                            List.Transform(
                                _,
                                (x) ⇒ Number.Power( x, 2 )
                            )
                        )
                }
            }
        ),

    Partition=
        Table.Partition(
            Profiling,
            "HHI",
            3,
            each
                List.Count(
                    List.RemoveFirstN(
                        { 1500, 2500 },
                        (x)⇒ x ‹ _
                    )
                )
        ),

    Outcome=
        List.Buffer(
            List.Transform(
                Partition,
                each
                Table.SelectColumns(
                    DB,
                    Table.Column(
                        _,
                        "Column"
                    )
                )
            )
        )
in
    Outcome

由于Table.Profile()是不会自动生成每一列的HHI,所以需要填写第二参数建立名称为HHI的列汇总。第二个参数的要点:(1)紧随第一个each的函数通过列的数据类型识别第二个each后面跟着的函数需要进行汇总的对象(特定数据类型的列),不符合特定数据类型的列在汇总列中的对应值为null。(2)第二个each传入的是DB按列分解所得的串列。Partition步骤的要点:(1)由于分组的组数为3,所以填入hash参数的函数结果只能为0/1/2。(2)List.RemoveLastN()第二个参数的条件判断过程类似米诺骨牌,每一个元素对应一张骨牌,如果第一个元素的结果为true它所对应的骨牌倒下,然后轮到下一个元素,整个过程直到第一张不倒下的骨牌出现为止,然后函数会把所有倒下的骨牌对应的元素移除。(3)如果HHI大于2500,经过List.RemoveLastN处理后的{1500, 2500}将会变成{},代入List.Count()为0;如果1500<HHI<=2500,经过List.RemoveLastN处理后的{1500, 2500}将会变成{2500},代入List.Count()为1;如果HHI<=1500,经过List.RemoveLastN处理后的{1500, 2500}将不变,代入List.Count()为2。分好组后,只需要把每一组的Column列传入Table.SelectColumns()就完成需要的转换。笔者最初的思路是使用Table.Group()分组,以上的Outcome步骤与Partition步骤就可以合二为一,但是并没有成功,希望熟悉Table.Group()的各位爱好者能分享一下使用Table.Group()的解法。

附件

One Reply to “Table.Profile()”

  1. Table.Group分组最后是同一个表吧,这里要分成三个表的话怎么样不都得用Table.Partition.
    let
    Profiling=
    Table.Group(
    Table.AddColumn(
    Table.Profile(
    DB,
    {
    {
    "HHI",
    each Type.Is( _, type nullable number),
    each
    List.Sum(
    List.Transform(
    _,
    (x) => Number.Power( x, 2 )
    )
    )
    }
    }
    )
    ,"组别"
    ,each if [HHI]>=2500 then 3 else if [HHI]>=1500 then 2 else 1
    ),
    "组别",
    {"column",each Table.SelectColumns(DB,[Column])}
    )
    in
    Profiling

发表评论

电子邮件地址不会被公开。 必填项已用*标注