动态合并和堆叠多组列 - Power Query

Merge and Stack Multiple Sets of Columns dynamically - Power Query

我有一个 csv 数据集,如下所示。我有多个这样的 csv 文件,一旦我找出单个文件的正确转换,我就想合并这些文件。这是包含此数据的 Sample Excel File

进入这个预期的输出:

输入数据大致分为 4 个部分:

1] 前 3 列用于创建 QuestionsAnswersLabel 列。

2] 百分比列的一部分。

3] 统计测试列的一部分。

4] 1 列的部分。

我想 Merge 每组列 R.1....R10 然后 Unpivot (Stack) 它们一个在另一个上面,如输出所示。 R1...R10 列计数可能每次都不同,但每个部分都是相同的,即 Percentage columnsStat testing columns1 columns.

在谷歌搜索时,我遇到了一个有点相似的 Imke Feldmann post on Merging and unpivoting columns dynamically using a custom function. However, i am unable to select and merge the different sections of columns dynamically. Also, i found Bill Szysz's post 并试图找出一种方法来修改他的第二个解决方案,即 Combine Method 在类似的 post。这是 Bill Szysz 的 Combine Method 解决方案。

let
    Source = Table.PromoteHeaders(Excel.CurrentWorkbook(){[Name="UglyData"]}[Content], [PromoteAllScalars=true]),
    Lists = Table.FromColumns({List.Transform({0..((List.Count(Table.ColumnNames(Source))-6)/5)-1}, each List.Range(Table.ColumnNames(Source), _*5+6, 5)) }),
    AlmostReady = Table.Combine(Table.AddColumn(Lists, "Columns", each Table.FromColumns({Table.Column(Source, Table.ColumnNames(Source){0})} & {List.Repeat({[Column1]{0}}, Table.RowCount(Source))} & List.Transform(List.Skip([Column1], 1), each Table.Column(Source, _)), {Table.ColumnNames(Source){0}, "Name"} & List.Transform(List.Skip([Column1], 1), each Text.BeforeDelimiter(_, "_")) )   )[Columns]),
    Ready = Table.AddColumn(AlmostReady, "Total", each List.Sum(List.Skip(Record.ToList(_), 2)))
in
    Ready

问题是,Bill 使用固定的列数和行数(5 和 6),而我的列数和行数可能会改变。例如今天每个部分有 10 组列,明天可能有 5 或 20 个。但是每个部分的列数将始终相同,即百分比部分、统计部分和数字部分。此外,列的顺序可能会更改,但在各部分中保持相同的顺序:

例如:

百分比部分| |统计部分 | | |数字部分 |

R1 | R3 | R2 | R5 | R4 | | R1 | R3 | R2 | R5 | R4 | | R1 | R3 | R2 | R5 | R4 |

这个数据很棘手,超出了我的业余技能。这可能吗?

这里是部分答案,因为我无法弄清楚你在找什么

它创建了三个表,每个表都有前三列,然后是后面的 XX 列。您可以根据需要将它们组合在一起

let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
List = Table.ColumnNames (Source),
Count = List.Count (List),
First = Table.SelectColumns(Source,List.FirstN(List,3)  & List.RemoveFirstN(List.RemoveLastN(List,(Count-3)/3*2),4)),
Second = Table.SelectColumns(Source,List.FirstN(List,3)  &  List.RemoveFirstN(List.RemoveLastN(List,(Count-3)/3),4+(Count-3)/3)),
Third = Table.SelectColumns(Source,List.FirstN(List,3)  &  List.RemoveFirstN(List,4+(Count-3)/3*2))
in Third

看看这是否适合你

let Source = Csv.Document(File.Contents("C:\temp\SampleCSV.csv"),[Delimiter=",", Encoding=1252, QuoteStyle=QuoteStyle.None]),
#"Promoted Headers" = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
// get list and count of columns
List = Table.ColumnNames (#"Promoted Headers" ),
Count = List.Count (List),
// get list of columns from first table and preserve to rename in last step
FirstNames = List.RemoveFirstN(List.RemoveLastN(List,(Count-3)/3*2),4),
// divide the table into three tables by section and combine
Headers = List.Combine ({{"Que","Label","Agg"},FirstNames,{"Answer","Question"}}),
First = Table.Skip(Table.DemoteHeaders(Table.SelectColumns(#"Promoted Headers" ,List.FirstN(List,3)  & FirstNames)),1),
Second = Table.Skip(Table.DemoteHeaders(Table.SelectColumns(#"Promoted Headers" ,List.FirstN(List,3)  &  List.RemoveFirstN(List.RemoveLastN(List,(Count-3)/3),4+(Count-3)/3))),1),
Third = Table.Skip(Table.DemoteHeaders(Table.SelectColumns(#"Promoted Headers" ,List.FirstN(List,3)  &  List.RemoveFirstN(List,4+(Count-3)/3*2))),1),
Combined = Table.Combine({First,Second,Third}),
// pull out the Question, Answer. Label, Que and fill down
#"Added Index" = Table.AddIndexColumn(Combined, "Index", 0, 1),
#"Added Custom" = Table.AddColumn(#"Added Index", "Answer", each try if  #"Added Index"{[Index]-1}[Column1] <> "" and [Column1] = "" then [Column2] else null otherwise null),
#"Added Custom1" = Table.AddColumn(#"Added Custom", "Custom", each try if [Column1]<> "" then [Column2] else null otherwise null),
#"Added Custom2" = Table.AddColumn(#"Added Custom1", "Custom3", each try if #"Added Index"{[Index]-1}[Column1] <> "" or [Column3]="" then "kill" else null otherwise "kill"),
#"Replaced Value" = Table.ReplaceValue(#"Added Custom2","",null,Replacer.ReplaceValue,{"Column1"}),
#"Filled Down" = Table.FillDown(#"Replaced Value",{"Answer", "Custom","Column1"}),
#"Filtered Rows" = Table.SelectRows(#"Filled Down", each ([Custom3] = null)),
#"Removed Columns" = Table.RemoveColumns(#"Filtered Rows",{"Index","Custom3"}),
// rename and reorder
#"Rename Columns" = Table.RenameColumns( #"Removed Columns", List.Zip( { Table.ColumnNames( #"Removed Columns" ),  Headers } )),
#"Reordered Columns" = Table.ReorderColumns(#"Rename Columns",List.Combine({{"Que", "Question", "Answer", "Label", "Agg"}, List.Sort(FirstNames)}))
in #"Reordered Columns"