【问题标题】:Powerquery - Converting single column information having column names and values to tablePowerquery - 将具有列名和值的单列信息转换为表
【发布时间】:2022-01-13 02:49:07
【问题描述】:

我在下面的单列中有一个数据

CName1
CName2
CName3
.
.
.
第 1 行 col1 值1
行 1 列 2 值 2
行 1 列 2 值 3
.
.
.
第 2 行 col1 值4
第 2 行 col2 值5
行 2 列 3 值 6
.
.
.
第 3 行 col1 值7
第 3 行 col2 值 8
第 3 行 col3 值9
.
.
.
.

我想要的是

CName1 CName2 CName3 ...... ...... .....
价值1 价值2 价值3 ...... ...... .....
价值4 价值5 价值6 ...... ...... .....
价值7 价值8 价值9 ...... ...... .....
...... ...... ...... ...... .....

如何做到这一点?

感谢您的帮助。

【问题讨论】:

  • 可能创建的列数有上限吗?组之间是否总是至少有一个空行?请展示您的尝试。
  • 项目是否用空格分隔?
  • @horseyride 我在想也许源数据中的组真的只有“值”参数,而行/列位置实际上并不存在。
  • @RonRosenfeld 你是对的。很抱歉造成混乱..

标签: transform powerquery


【解决方案1】:

这是一种方法:

假设

  • 每个数据行中的位置条目实际上并不存在
    • 如果是,我们将修改算法
  • 所有列标题都在第一组中
  • 每个组至少由一个空行分隔
  • 每个组的列从第一列开始(但它们不必都具有相同的列数)

请阅读代码 cmets,并探索 Applied Steps 窗口,以了解算法

M 代码
已编辑以从最后一行删除硬编码的列名

let
    Source = Excel.CurrentWorkbook(){[Name="Table12"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Column1", type text}}),

//add shifted column
    shifted = Table.FromColumns(
                Table.ToColumns(#"Changed Type") &    
                    {{null} & List.RemoveLastN(#"Changed Type"[Column1])},
                type table[Column1=text, shiftedCol1 =text]),

//create a column which adds an index number at the first row of each group
//then fill down to create a column on which to group
    #"Added Index" = Table.AddIndexColumn(shifted, "Index", 0, 1, Int64.Type),
    #"Added Custom" = Table.AddColumn(#"Added Index", "grouper", each if [Column1] <> null and [shiftedCol1] = null then [Index] else null),
    #"Removed Columns" = Table.RemoveColumns(#"Added Custom",{"Index"}),
    #"Filled Down" = Table.FillDown(#"Removed Columns",{"grouper"}),
    #"Removed Columns1" = Table.RemoveColumns(#"Filled Down",{"shiftedCol1"}),

//remove the empty rows
    #"Filtered Rows" = Table.SelectRows(#"Removed Columns1", each ([Column1] <> null)),

//group by the "grouper" column
//then transpose each sub table
    #"Grouped Rows" = Table.Group(#"Filtered Rows", {"grouper"}, {
        {"transpose", each Table.Transpose(Table.SelectColumns(_,"Column1"))}
        }),
    #"Removed Columns2" = Table.RemoveColumns(#"Grouped Rows",{"grouper"}),

//combine the grouped subtables, and promote the headers
    comb = Table.Combine(#"Removed Columns2"[transpose]),
    #"Promoted Headers" = Table.PromoteHeaders(comb, [PromoteAllScalars=true]),
    #"Changed Type1" = Table.TransformColumnTypes(#"Promoted Headers",
        List.Transform(Table.ColumnNames(#"Promoted Headers"), each {_, type text}))
in
    #"Changed Type1"

编辑
如果如您的 cmets 中所暗示的那样,数据集之间确实没有空白行,但您知道最终结果中的列数,

  • 硬编码列数(或将其设置为参数)
  • 通过对 Index 列执行 IntegerDivide 来更改“grouper”列的构造方式,而不是我在上面使用的公式。

M 码

let
    Source = Excel.CurrentWorkbook(){[Name="dataTable"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Data", type text}}),

//hard coded number of columns
    numCols = 3,

//add grouper
    #"Added Index" = Table.AddIndexColumn(#"Changed Type", "Index", 0, 1, Int64.Type),
    #"Inserted Integer-Division" = Table.AddColumn(#"Added Index", "grouper", each Number.IntegerDivide([Index], numCols), Int64.Type),
    #"Removed Columns" = Table.RemoveColumns(#"Inserted Integer-Division",{"Index"}),

//group by the "grouper" column
//then transpose each sub table
    #"Grouped Rows" = Table.Group(#"Removed Columns", {"grouper"}, {
        {"transpose", each Table.Transpose(Table.SelectColumns(_,"Data"))}
        }),
    #"Removed Columns2" = Table.RemoveColumns(#"Grouped Rows",{"grouper"}),

//combine the grouped subtables, and promote the headers
    comb = Table.Combine(#"Removed Columns2"[transpose]),
    #"Promoted Headers" = Table.PromoteHeaders(comb, [PromoteAllScalars=true]),
    #"Changed Type1" = Table.TransformColumnTypes(#"Promoted Headers",
        List.Transform(Table.ColumnNames(#"Promoted Headers"), each {_, type text}))
in
    #"Changed Type1"

【讨论】:

  • 感谢破译
  • 谢谢,我会试试的。
  • 嗨,罗恩,这段代码在给定的假设下工作得很好。我需要更详细地了解我的情况(1)M 代码具有硬编码的列名(Cname1、Cname2 ...),可以从数据中获取而不是在代码中进行硬编码。 (2) 我可以知道有多少个变量(列),我们可能没有组之间的空行。示例列 (data,name,age,city,John,33,New York,Jane,21,Toronto,Tom,33,Delhi,Tim,55,London) ',' 表示新行。在这个数据中我有 3 列,在另一个数据中我可能有 5 列......抱歉打扰了。我迷路了。感谢您提供详细信息。
  • @PrasannaDhakephalkar 关于硬编码的列名,这是一个疏忽。将该行更改为#"Changed Type1" = Table.TransformColumnTypes(#"Promoted Headers",List.Transform(Table.ColumnNames(#"Promoted Headers"), each {_, type text}))。我将编辑我的答案以表明这一点。
  • @PrasannaDhakephalkar 还添加了假设已知(硬编码)列数的代码;并且数据集之间没有空行。这只改变了您构建“grouper”列的方式,但基本算法保持不变。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 2021-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多