暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Power Query M语言实例 | 表中的新旧值替换

2072

在实际的数据清洗与转换过程中,替换是必不可少的动作,并且很多时候需面临各类复杂的替换,因此与替换相关的操作值得花时间去深究。


01

Table.ReplaceValue()


Table.ReplaceValue()函数用于将表中新、旧值进行替换,第2个和第3个参数为any(任意类型,如列表、文本或数值等),第4个参数为参数函数(replacer替换器函数),这3个参数是Table.ReplaceValue()函数的核心。Table.ReplaceValue()函数的拓展性强,可应用于各类复杂的替换场合,语法如下:

    Table.ReplaceValue(
    table as table,
    oldValue as any, //Y
    newValue as any, //Z
    replacer as function, //分ReplaceText或ReplaceValue两种情形
    columnsToSearch as list //X
    as table


    1

    基础语法

    该函数常用于各种场合的横向填充、纵向替换。理解与上手该函数的最有效的方式是通过Power Query编辑器中的图形化操作为“转换”→“替换值”获取该函数的完整代码,然后进行代码的修改。通过“数据”→“从表格”将数据导入Power Query编辑器,数据源如图9-55所示。


    ■ 图9-55 数据源


    以表内的“横向填充”为例。操作步骤如下: 单击“城市”列,选择“转换”→“替换值”→“替换值”。对于一些复杂的替换场景,出于后续修改的需要,可先预设置一些个人习惯的占位符。例如,将“要查找的值”设置为null,将“替换为”设置为0,单击“确定”按钮,如图9-56所示。


    ■ 图9-56 替换值


    在编辑栏查看显示的代码如下:

      = Table.ReplaceValue(源,null,"0",Replacer.ReplaceValue,{"城市"})

      在以上代码中,0值是临时占位的一种应用。

      如果要替换的列为两列或者更多列也是允许的。例如,选择“省份”和“城市”两列,选择“转换”→“替换值”→“替换值”,将null替换为0。在编辑栏查看显示的代码如下:

        = Table.ReplaceValue(源,null,"0",Replacer.ReplaceValue,{"省份", "城市"})

        对比显示的这两个代码块不难发现。Table.ReplaceValue()函数的第5个参数可以轻松地进行列选择,在图形化操作界面中操作时很好理解,但如果代码化来完成{"城市"}或{"省份", "城市"},对于初学者来讲则相对不易理解与记忆。

        修改上面的第1个代码块,对表内的数据实施引用(注意: 第2个和第3个参数在引用或调用的过程中,前面必须加each),实现横向填充,代码如下:

          = Table.ReplaceValue(源,null,each [省份],Replacer.ReplaceValue,{"城市"})

          实现的效果如图9-57所示。


          ■ 图9-57 横向填充


          在“高级编辑器”中查看的完整代码如下:

            //ch9-053
            let
            源 = Excel.CurrentWorkbook(){[Name="表6"]}[Content],
            替换 = Table.ReplaceValue(源,null,each [省份],Replacer.ReplaceValue,{"城市"})
            in
                替换

            以上操作也能通过表间数据的调用与匹配实现。导入“表6”和“表6A”,用“表6A”中的数据替换“表6”中的空值,数据源如图9-58所示。


            ■ 图9-58 数据源


            在“高级编辑器”中查看的完整代码如下:

              //ch9-054
              let
              A = Excel.CurrentWorkbook(){[Name="表6A"]}[Content],
              源 = Excel.CurrentWorkbook(){[Name="表6"]}[Content],
              替换 = Table.ReplaceValue(源,
              null,
              each A{[省份=[省份]]}[城市],
              Replacer.ReplaceValue,
              {"城市"}
              )
              in
                 替换

              返回的值与图9-57所示的值相同。

              或者,将第4个参数更改为自定义函数,在编辑栏显示的代码如下:

                = Table.ReplaceValue(源,null,each [省份],(x,y,z)=>if x is null then z else x,{"城市"})

                返回的值与图9-57所示的值相同。在“高级编辑器”中查看的完整代码如下:

                  //ch9-055
                  let
                  源 = Excel.CurrentWorkbook(){[Name="表6"]}[Content],
                  替换 = Table.ReplaceValue(
                  源,
                  null,
                  each [省份],
                  (x,y,z)=>if x is null then z else x,
                  {"城市"}
                  )
                  in
                    替换

                  在以上代码中,通过自定义的方式来定义参数函数从而控制替换前、替换后的值。本案例中,y 值(替换前的值)没有参与运算。


                  2

                  进阶语法

                  Table.ReplaceValue()函数威力的大小在于第2个、第3个和第4个参数的协同应用的深度。第2个参数(y)为替换前的值,第3个参数(z)为替换后的值,第4个参数为替换器函数(当替换的过程中不需要自定义参数函数时,该函数保持系统生成的原样即可)。

                  有关第2个参数的补充: 将null值替换为0是最简单、最易理解的单值替换。以“表3”为例,在实际应用场景中,将([Q1]+[Q2])185或者List.Sum({[Q1], [Q2]}) 185的“城市”添加“(A+)”标识。此时的第2个参数已经是多值或列表,这种情形也是允许的,但需要第3个和第4个参数的配合才能产生效果。

                  有关第3个参数的补充: 将null值替换为0是最简单、最易理解的单值替换。在实际应用场景中,第3个参数可能为{“(A+)”,“(A)”,“A-”},它是也允许的,但需要第2个参数与第4个参数的配合才能完成。

                  有关第4个参数的补充: 在默认情况下,系统生成的样式为Replacer.ReplaceValue(精确匹配)或Replacer.ReplaceText(模糊匹配)。以Replacer.ReplaceValue为例,它其实是(x,y,z)= Replacer.ReplaceValue(x,y,z)的简写; 其中x 对应的是选择一列或多列,y 为替换前的值,z 为替换后的值。当将此参数函数修改为自定义函数时,必须先理解x、y、z所代表的对象,然后理解替换对象间的逻辑关系,这样才能正确、高效地进行替换。


                  3

                  进阶应用

                  在Table.ReplaceValue()函数的5个参数中,第2个、第3个和第4个参数需重点理解。在运用自定义函数的过程中,第5个参数(Columns)为x、第2个参数为y(oldValue)、第3个参数为z(newValue),它是第4个参数中x、y、z 的对应值(注意: 第4个参数在应用过程中可能不需要x、y、z 全部上场,它们三者中的1个或2个上场也是允许的,视实际需要而定)。

                  以“表6”为例,当第2个参数为列表时,通过第4个参数的协同来完成相关替换,完整代码如下:

                    //ch9-056
                    let
                    源 = Excel.CurrentWorkbook(){[Name="表6"]}[Content],
                    替换 = Table.ReplaceValue(
                    源,
                    {"北京","上海","广州","深圳"},
                    "一线",
                    (x,y,z)=> if List.Contains(y,x) then z else x,
                    {"省份", "城市"}
                    )
                    in
                      替换

                    以上代码中,第2参数为列表,所以第4参数必须用列表函数来控制。运行结果如图9-59所示。


                    ■ 图9-59 ch9-056的运行结果


                    以“表3”为例,代码如下:

                      //ch9-057
                      let
                      源 = Excel.CurrentWorkbook(){[Name="表3"]}[Content],
                      取一部分数据 = Table.AlternateRows(源,1,2,1),
                      替换 = Table.ReplaceValue(
                      取一部分数据,
                      each {[Q1],[Q2]},
                      "(A+)",
                      (x,y,z)=> if List.Sum(y)>185 then x&z else x,
                      { "城市"}
                      )
                      in
                        替换

                      以上代码也可以更改,更改后的代码如下:

                        //ch9-058
                        let
                        源 = Excel.CurrentWorkbook(){[Name="表3"]}[Content],
                        取一部分数据 = Table.AlternateRows(源,1,2,1),
                        替换 = Table.ReplaceValue(
                        取一部分数据,
                        each [Q1]+[Q2],
                        "(A+)",
                        (x,y,z)=> if y>185 then x&z else x,
                        {"城市"}
                        )
                        in
                          替换

                        以上两个代码块返回的值完全相同,如图9-60所示。


                        ■ 图9-60 ch9-058的运行结果


                        当第2个和第3个参数都为列表时,通过第4个参数来控制替换对象是允许的,第5个参数为多列也是允许的,代码如下:

                          //ch9-059
                          let
                          源 = Excel.CurrentWorkbook(){[Name="表3"]}[Content],
                          取一部分数据 = Table.AlternateRows(源,1,2,1),
                          类型 = Table.TransformColumnTypes(取一部分数据,{{"排名", type text}}),
                          替换 = Table.ReplaceValue(
                          类型,
                          each {[Q1],[Q2]},
                          {"(A+)","(A)","(A-)"},
                          (x,y,z)=> if List.Sum(y)>185 then x&z{0}
                          else if List.Sum(y)>165 then x&z{1} else x&z{2},
                          {"城市","排名"}
                          )
                          in
                            替换

                          运行结果如图9-61所示。


                          ■ 图9-61 ch9-059的运行结果

                          从以上学习中不难发现: 学习M 语言的价值在于能够实现图形化操作所不能实现的功能。低成本的学习方法在于: 对于难于理解与记忆的函数,可以先通过图形化获取相关代码,然后在系统生成的代码的基础上进行代码的修改。


                          02

                          Table.ReplaceErrorValues()


                          Table.ReplaceErrorValues()函数用于将错误值替换为指定的新值,语法如下:

                            Table.ReplaceErrorValues(
                            table as table,
                            errorReplacement as list
                            as table

                            应用举例,代码如下:

                              //ch9-060
                              let
                              a= #table(
                              {"运单","客户"},
                              {{"YD001","王2"},{"YD003","张3"}, {"YD005","李"&4}}
                              )
                              in
                                  a

                              返回的值“YD005”的“客户”列存在错误,如图9-62所示。


                              ■ 图9-62 存在错误值的表


                              在 Power Query编辑器中,选择“客户”列,单击“转换”→“替换值”→“替换错误”。在“替换错误”对话框中输入值(例如,“李4”),单击“确定”按钮,如图9-63所示。


                              ■ 图9-63 替换错误


                              在编辑栏显示的代码如下:

                                = Table.ReplaceErrorValues(a, {{"客户", "李4"}})

                                将以上代码中的{{"客户", "李4"}}(两对花括号)替换为{"客户", "李4"}(1对花括号)是允许的。


                                03

                                Table.Transpose()


                                Table.Transpose()函数用于表的转置,使列变为行、使行变为列。此函数的用法较为简单,语法如下:

                                  Table.Transpose(
                                  table as table,
                                  optional columns as any
                                  as table

                                  应用举例,代码如下:

                                    //ch9-061
                                    let
                                    源 = Excel.CurrentWorkbook(){[Name="表1"]}[Content],
                                    降级 = Table.DemoteHeaders(源),
                                    转置 = Table.Transpose(降级)
                                    in
                                    转置

                                    运行结果如图9-64所示。


                                    ■ 图9-64 ch9-061的运行结果



                                    04

                                    参考书籍

                                    《深入浅出Power Query M语言》

                                    ISBN:9787302602828

                                    黄福星 编著

                                    定价:100元



                                    内容简介

                                    本书系统阐述Power Query M语言从基础到进阶的应用,包括应用流程、应用技巧等。本书通过一种易于理解的方式,旨在让读者用一个月的时间,系统、全面地掌握M语言。

                                    全书共分为5篇:第一篇为入门篇(第1和2章),第二篇为基础篇(第3~5章),第三篇为强化篇(第6~8章),第四篇为进阶篇(第9~11章), 第五篇为案例篇(第12章)。书中主要内容包括Power BI简介、Power Query基础、M语言基础、文本处理、时间智能、数据转换、数据处理、数据分组、数据获取、综合应用。

                                    本书适用于零基础学习Power Query M语言的读者,包括财务、人事行政、电商客服、质量统计等与数据分析密切相关的从业人员,也可作为高等院校、IT培训机构、其他编程爱好者的参考用书或教材。


                                    编辑推荐

                                    本书以M语言中高频使用的函数为依托,通过一组简单、易于理解的数据源并且方便读者动手实践的方式,循序渐进地讲解,以此来演绎上百个实用案例,从而有效地实现本书的写作目标:“让所有的读者一个月之内对M语言函数有一个直观、清晰的了解,并能轻松上手”。




                                    文章转载自清华计算机学堂,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                    评论