【问题标题】:Transpose table partially部分转置表
【发布时间】:2020-05-07 21:46:52
【问题描述】:

我有一个 CSV 文件,其中包含有关某些生产批次的信息。当加载到 Excels PowerQuery 编辑器中时,表格如下所示:

批次日期 RawMaterial1 RawMaterial2 RawMaterial3 Amount1 Amount2 Amount3 123 01.01.2020 铁铬镍 70 19 11 234 01.02.2020 铁铬镍 72 17 9

为了使这张表更具可读性,我正在寻找一种方法来将其部分转置以将其转换为如下格式:

批次日期 RawMaterials 数量 123 01.01.2020 铁 70 铬 19 倪11 234 01.02.2020 铁 72 铬 17 倪11

有没有办法单独使用 PowerQueryM 来实现这一点?

【问题讨论】:

    标签: excel transpose powerquery m


    【解决方案1】:

    这似乎有效

    取消透视除前两列之外的所有列

    复制数据列

    将列类型更改为数字以强制在非数字列上出错

    将所有错误更改为可识别的内容,例如 999999999999

    根据它过滤成两个表,并为每个表添加一个索引

    将两个表合并在一起

    添加新列,使用索引查看Batch是否与前一行相同以消除重复

    let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(Source, {"Date", "Batch"}, "Attribute", "Value"),
    #"Duplicated Column" = Table.DuplicateColumn(#"Unpivoted Other Columns", "Value", "Value - Copy"),
    #"Changed Type" = Table.TransformColumnTypes(#"Duplicated Column",{{"Value - Copy", type number}}),
    #"Replaced Errors" = Table.ReplaceErrorValues(#"Changed Type", {{"Value - Copy", 999999999999999}}),
    #"Filtered Rows" = Table.SelectRows(#"Replaced Errors", each ([#"Value - Copy"] = 999999999999999)),
    #"Filtered Rows2" = Table.SelectRows(#"Replaced Errors", each ([#"Value - Copy"] <> 999999999999999)),
    Index1 = Table.AddIndexColumn(#"Filtered Rows", "Index", 0, 1),
    Index2 = Table.AddIndexColumn(#"Filtered Rows2", "Index", 0, 1),
    #"Merged Queries" = Table.NestedJoin(Index2,{"Index"},Index1,{"Index"},"Index3",JoinKind.LeftOuter),
    #"Expanded Index3" = Table.ExpandTableColumn(#"Merged Queries", "Index3", {"Value"}, {"Value.1"}),
    #"Removed Columns" = Table.RemoveColumns(#"Expanded Index3",{"Attribute", "Value - Copy"}),
    #"Added Custom" = Table.AddColumn(#"Removed Columns", "Batch.1", each if [Index] = 0 then [Batch] else if #"Removed Columns"{[Index]-1}[Batch] = [Batch] then null else [Batch]),
    #"Added Custom2" = Table.AddColumn(#"Added Custom", "Date.1", each if [Index] = 0 then [Date] else if #"Removed Columns"{[Index]-1}[Batch] = [Batch] then null else [Date]),
    #"Removed Columns1" = Table.RemoveColumns(#"Added Custom2",{"Batch", "Date", "Index"}),
    #"Reordered Columns" = Table.ReorderColumns(#"Removed Columns1",{"Batch.1", "Date.1", "Value.1", "Value"})
    in  #"Reordered Columns"
    

    【讨论】:

    • 干得好!这行得通。作为奖励,我很想知道您是否可以将重复的文本更改为空字符串(如果它们在连续的行中,请参阅初始问题)。这将再次提高表格的可读性。
    【解决方案2】:

    这可以更简单地完成:

    let
        Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],,
        #"Changed Type" = Table.TransformColumnTypes(Source,{{"Batch", Int64.Type}, {"Date", type date}, {"RawMaterial1", type text}, {"RawMaterial2", type text}, {"RawMaterial3", type text}, {"Amount1", Int64.Type}, {"Amount2", Int64.Type}, {"Amount3", Int64.Type}}),
        #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Changed Type", {"Batch", "Date"}, "Attribute", "Value"),
        #"Split Column by Character Transition" = Table.SplitColumn(#"Unpivoted Other Columns", "Attribute", Splitter.SplitTextByCharacterTransition((c) => not List.Contains({"0".."9"}, c), {"0".."9"}), {"Type", "Index"}),
        #"Pivoted Column" = Table.Pivot(#"Split Column by Character Transition", List.Distinct(#"Split Column by Character Transition"[Type]), "Type", "Value")
    in
        #"Pivoted Column"
    
    1. 取消透视除前两列之外的所有列。
    2. 将属性列拆分为文本部分和索引部分(在 GUI 中:转换 > 拆分列 > 按非数字到数字)。
    3. 转回文本部分列(在 Pivot Column Advanced 选项中选择 Don't Aggregate)。

    【讨论】:

      【解决方案3】:

      首先非常感谢@horseyride。我从您建议的代码中学到了很多东西。可悲的是,当我尝试将日期列添加到 unpivot 区域时,我在代码中发现了一个小缺陷。但由于我从中吸取的教训,我能够制作出一个稍微通用的版本,它基本上遵循相同的算法。

      let
          Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
          #"Changed Type" = Table.TransformColumnTypes(Source,{{"Date", type date}}),
          #"Unpivot Columns" = Table.UnpivotOtherColumns(#"Changed Type", {"Batch"}, "Attribut", "Wert"),
          Filter1 = Table.SelectRows(#"Unpivot Columns", each ([Attribut] <> "Amount1" and [Attribut] <> "Amount2" and [Attribut] <> "Amount3")),
          ModFilter1 = Table.AddColumn(Filter1, "Benutzerdefiniert", each if [Attribut] = "Date" then [Attribut] else [Wert], type text),
          Filter2 = Table.SelectRows(#"Unpivot Columns", each ([Attribut] <> "RawMaterial1" and [Attribut] <> "RawMaterial2" and [Attribut] <> "RawMaterial3")),
          #"IndexFilter1" = Table.AddIndexColumn(ModFilter1, "Index", 0, 1),
          #"IndexFilter2" = Table.AddIndexColumn(Filter2, "Index", 0, 1),
          #"Join Filtered Indexes" = Table.NestedJoin(IndexFilter1,{"Index"},IndexFilter2,{"Index"},"IndexFilter2",JoinKind.LeftOuter),
          #"Expand Joined Column" = Table.ExpandTableColumn(#"Join Filtered Indexes", "IndexFilter2", {"Wert"}, {"IndexFilter2.Wert"}),
          #"Remove Columns" = Table.RemoveColumns(#"Expand Joined Column",{"Index", "Attribut", "Wert"}),
          #"Rename Columns" = Table.RenameColumns(#"Remove Columns",{{"Benutzerdefiniert", "Attribut"}, {"IndexFilter2.Wert", "Wert"}})
      in
          #"Rename Columns"
      

      我一直检查 horseyrides 的答案是否正确,因为他按原样解决了我最初的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-07-01
        • 2014-09-03
        • 1970-01-01
        • 1970-01-01
        • 2014-08-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多