Power Query 根据另一列转换一列

Power Query Transform a Column based on Another Column

我一直认为这应该很容易,但答案却在躲避我。在 Excel Power Query 中,我想根据另一列的值转换列的每一行中的值。例如,假设我有如下表 1:

Column A | Column B
-------------------
X        | 1
Y        | 2

我想根据B列中的值转换A列中的值,而不必添加新列并替换原来的A列。我尝试过使用TransformColumns,但输入只能是目标列的值 - 我无法从 TransformColumns 函数中访问 row/record 中的其他字段值。我会喜欢能够做这样的事情:

=Table.TransformColumns(Table1, {"Column A", each if [Column B]=1 then "Z" else _ })

这将导致:

Column A | Column B
-------------------
Z        | 1
Y        | 2

我知道有很多方法可以做到这一点,但我正在尝试找到一种 steps/transformations 最少的方法。例如,我知道我可以使用 Table.AddColumn 添加一个 new 基于查看 B 列的函数的 A 列,但是我必须删除原始的 A 列和将其替换为需要多个额外步骤的新列 A。

您不能通过这样的步骤转换现有列。使用新列,进行转换,然后删除现有列。有什么大不了的?在 Excel 中,您也不会期望公式会更改不同列的值。在 Power Query 中,公式的结果也存储在列中,并且不能是提供公式输入值之一的列。

我是这样完成的:

Table1:
Column A | Column B
-------------------
X        | 1
Y        | 2

= Table.FromRecords(Table.TransformRows(Table1,
    (r) => Record.TransformFields(r,
        {"A", each if r[Column B]="1" then "Z" else _})))

结果:

Column A | Column B
-------------------
Z        | 1
Y        | 2

这样您就可以通过在 Record.TransformFields 函数中使用嵌套列表一次转换多个列。

另一种选择是:

= Table.ReplaceValue(Table1, each [Column A], each if [Column B]=1 then "Z" else [Column A] , Replacer.ReplaceText, {"Column A"})

该代码更具可读性,但一次只能应用于一列。

其中大部分可以使用 UI 生成,如下所示:http://www.thebiccountant.com/2017/07/23/transforming-a-column-with-values-from-another-column-in-powerbi-and-powerquery-in-excel/

感谢 LoganTheSnowEater...我喜欢你的回答。您提到它可以针对多项操作进行扩展,我想 post 一个我如何成功使用它的示例:

#"Patch Records" = Table.FromRecords(Table.TransformRows(#"Sorted Rows",
(r) => Record.TransformFields( r, {
    {"Min Commit", each 
        if r[service_id] = "21430" then 81 else
        if r[service_id] = "24000" then 230 else
        if r[service_id] = "24008" then 18 else
        if r[service_id] = "24009" then 46.9 else
        _},
    {"Installed", each 
        if r[service_id] = "21430" then 90 else
        if r[service_id] = "24000" then 230 else
        if r[service_id] = "24008" then 18 else
        if r[service_id] = "24009" then 52 else
        _},
    {"Requested", each 
        if r[service_id] = "21430" then 90 else
        if r[service_id] = "24000" then 230 else
        if r[service_id] = "24008" then 18 else
        if r[service_id] = "24009" then 52 else
        _}})))

我唯一感到惊讶的是,我必须在完成后重置所有数据类型,但回想起来这是有道理的。

p.s。我没有足够的声誉点数 post 这作为对解决方案的评论

为了建立 LoganTheSnowEater 的答案,这里有一种方法可以使用 Table.FromRecords 中的第二个参数保留 table 列类型,如 M Reference 中指定:

Table1:
Column A | Column B
-------------------
    X    |    1
    Y    |    2

编辑:已更新以使用更好的方法从 table 中提取 table 类型,使用 Value.Type - 此外,为了完整性而修饰一次修改多个列。感谢 Value.Type 这个伟大的车队:https://social.technet.microsoft.com/Forums/en-US/636e9b44-6820-4ff2-ab60-5dd6a5307bd2/type-conversion-mysteries

=Table.FromRecords(
    Table.TransformRows(
        Table1,
        (r) => 
        Record.TransformFields(
            r,
            {
                {"Column A", each if r[Column B]="1" then "Z" else _},
                {"Column B", each if r[Column A]="Y" then "99" else _}
            }
        )
    ),
    Value.Type(Table1)
)

抱歉,我不太擅长编辑公式,现在可以使用了:

= Table.ReplaceValue(   #"Removed Columns", 
                   each [Contract Start Date],
                    each if [Contract Start Date] < #date(2019,01,01) then #date(2019,01,01) else
                          [Contract Start Date]
                    ,Replacer.ReplaceValue,
                    {"Contract Start Date"})