【问题标题】:Convert rows to columns in PowerQuery. Transpose & Pivot methods not giving correct results在 Power Query 中将行转换为列。转置和枢轴方法没有给出正确的结果
【发布时间】:2019-10-04 10:50:30
【问题描述】:

我在 Excel 中有一个名为“On Holds”的 PowerQuery 表,如下所示:

| Action User | Index |
|-------------|-------|
| Employee A  | 1     |
| Employee B  | 1     |
| Employee B  | 1     |
| Employee B  | 1     |
| Employee C  | 1     |
| Employee C  | 1     |
| Employee C  | 1     |
| Employee C  | 1     |
| Employee C  | 1     |
| Employee D  | 1     |
| Employee D  | 1     |
| Employee D  | 1     |

我希望将其转换为如下所示(它会有列标题,但我不介意它们是什么):

| Employee A | 1 |   |   |   |   |
| Employee B | 1 | 1 | 1 |   |   |
| Employee C | 1 | 1 | 1 | 1 | 1 |
| Employee D | 1 | 1 | 1 |   |   |  

我有一个单独的表 (TeamMembers),其中列出了我尝试加入以创建此列表但最终得到与原始表类似的版本的唯一员工姓名。

我可以使用 VBA 或 Powerquery 之外的一系列转置公式来实现,但我觉得这不是最好的方法 - 公式需要每周更新以考虑不同的行数。

任何帮助将不胜感激。


一个基本的转置不起作用,因为它最终是这样的:

| Column1    | Column2    | Column3    | Column4    | Column5    | Column6    |
|------------|------------|------------|------------|------------|------------|
| Employee A | Employee B | Employee B | Employee B | Employee C | Employee C |
| 1          | 1          | 1          | 1          | 1          | 1          |

一个支点最终是这样的:

| Employee A | Employee B | Employee C | Employee D |
|------------|------------|------------|------------|
| 1          | 3          | 5          | 3          |  

【问题讨论】:

    标签: excel powerquery


    【解决方案1】:

    总体技巧是在表中获取一个具有 Action User 累积计数的新列:

    选择操作用户列。 Group By ... [x] Basic,Group by:Action User,新列名称:Count,Operation:Count Rows [ok]

    并从

    修改生成的代码
    = Table.Group(Source, {"Action User"}, {{"Count", each Table.RowCount(_), type number}})
    

    = Table.Group(Source, {"Action User"}, {{"Count", each Table.AddIndexColumn(_, "Cum",1,1), type table}})
    

    通过单击计数列标题旁边的箭头来展开索引和累积

    选择 Cum 列、Pivo​​t 列..,使用 Index as Values Column [x] 高级选项,不要聚合

    完整代码如下

    let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    #"Grouped Rows" = Table.Group(Source, {"Action User"}, {{"Count", each Table.AddIndexColumn(_, "Cum",1,1), type table}}),
    #"Expanded Count" = Table.ExpandTableColumn(#"Grouped Rows", "Count", {"Index", "Cum"}, {"Index", "Cum"}),
    #"Pivoted Column1" = Table.Pivot(Table.TransformColumnTypes(#"Expanded Count", {{"Cum", type text}}, "en-US"), List.Distinct(Table.TransformColumnTypes(#"Expanded Count", {{"Cum", type text}}, "en-US")[Cum]), "Cum", "Index")
    in #"Pivoted Column1"
    

    【讨论】:

    • 快速提问 - 如果Index 列是按升序排列的各种数字,例如,Employee B 有数字 7、443 和 913,为什么数字不保留按数字顺序?它显示为 443、7、913,这似乎是一种文本排序,列类型显示 ABC123 而不仅仅是 123。我可以添加一些东西来保持它们的数字顺序吗?
    • 我的显示为原始排序,所以不知道为什么。试试下面的亚历克西斯
    • 道歉 - 如果我记得先排序,它会以正确的顺序显示。我在示例中未显示的列是“Cumm. Days on Hold”,#"Sorted Rows" = Table.Sort(#"Filtered Rows",{{"Action User", Order.Ascending}, {"Cumm. Days on Hold", Order.Ascending}}), 正确显示了所有内容。再次感谢您的帮助。
    【解决方案2】:

    另一种方法是执行 Group By 并更改您的聚合函数。连接而不是总和/最大值/平均值。然后,您可以按您在连接 Text.Combine 函数中使用的分隔符进行拆分。

    当您执行 Group By 时,步骤通常如下所示:

    = Table.Group(Source, {"ActionUser"}, {{"Sum", each List.Sum([Index]), type number}})
    

    我所做的是将List.Sum([Index]) 替换为以下内容:

    Text.Combine(List.Transform([Index], Text.From), ",")
    

    这会将数字转换为文本,然后将它们与Text.Combine 连接起来,使用逗号作为分隔符,得到如下表格:

    从这里开始,Transform > Split Column > By Delimiter 将完成这项工作。


    完整的 M 码:

    let
        Source = Table1,
        #"Grouped Rows" = Table.Group(Source, {"ActionUser"}, {{"Concat", each Text.Combine(List.Transform([Index], Text.From), ","), type text}}),
        #"Split Column by Delimiter" = Table.SplitColumn(#"Grouped Rows", "Concat", Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv), {"Concat.1", "Concat.2", "Concat.3", "Concat.4", "Concat.5"}),
        #"Changed Type" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Concat.1", Int64.Type}, {"Concat.2", Int64.Type}, {"Concat.3", Int64.Type}, {"Concat.4", Int64.Type}, {"Concat.5", Int64.Type}})
    in
        #"Changed Type"
    

    【讨论】:

    • 感谢@Alexis 的回复。我对这个答案的问题是它只显示了五列数据(这就是我的示例所具有的)。我的实际数据有可变数量的列 - 目前最小值为 1 列,最大值为 28 列。
    • 是的。对于可变列,可以使其更具动态性,但在这种情况下,horseyride 的解决方案可能会更好。
    【解决方案3】:

    作为变体

    let
       Source = Excel.CurrentWorkbook(){[Name="Table2"]}[Content],
       #"Changed Type" = Table.TransformColumnTypes(Source,{{"Action User", type text}, {"Index", type text}}),
       #"Grouped Rows" = Table.Group(#"Changed Type", {"Action User"}, {{"Count", each _[Index]}}),
       Custom1 = Table.FromColumns(#"Grouped Rows"[Count],#"Grouped Rows"[Action User]),
       #"Demoted Headers" = Table.DemoteHeaders(Custom1),
       #"Transposed Table" = Table.Transpose(#"Demoted Headers")
    in
       #"Transposed Table"
    

    【讨论】:

    • 虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。请edit您的答案添加解释并说明适用的限制和假设。
    猜你喜欢
    • 2015-12-02
    • 1970-01-01
    • 1970-01-01
    • 2017-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-09
    相关资源
    最近更新 更多