Forum Discussion
enoch99
2 years agoHelper I
Transforming data as indicated
Hello everyone, I have a table like the one below, and I wanted to tranform it to two different structucture. The sample of original table is: 1. First I want to tranform the table to:...
- 2 years ago
To create the first table:
Data
Month Place Engineer Girls<17 Boys <17 Women Adult Men Adult Elderly Women Elderly Men Doctor Girls<172 Boys <173 Women Adult4 Men Adult5 Elderly Women6 Elderly Men7 Teacher Girls<178 Boys <179 Women Adult10 Men Adult11 Elderly Women12 Elderly Men13 January Place A Yes 2 0 1 4 1 1 Yes 0 0 1 2 3 2 Yes 1 2 2 3 1 5 January Place B No 0 0 0 0 0 0 Yes 0 0 0 2 3 1 Yes 1 3 4 4 5 6 February Place A Yes 0 0 2 1 0 0 No 0 0 0 0 0 0 Yes 0 0 0 0 0 1 let //Change next line to reflect your actual data source Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content], #"Month/Place/Profession" = List.Alternate(Table.ColumnNames(Source),6,1,3), #"Base Attributes" = List.FirstN(List.RemoveFirstN(Table.ColumnNames(Source),3),6), //Replace nulls with 0's to retain all rows when we unpivot #"Replace Null with 0" = Table.ReplaceValue(Source,null,0, Replacer.ReplaceValue,List.RemoveMatchingItems(Table.ColumnNames(Source),#"Month/Place/Profession")), unPivot = Table.UnpivotOtherColumns(#"Replace Null with 0", {"Month","Place"},"Attribute","Value"), //Add column just for Professions #"Added Custom" = Table.AddColumn(unPivot, "Profession", each if [Value]="Yes" or [Value]="No" then [Attribute] else null), #"Filled Down" = Table.FillDown(#"Added Custom",{"Profession"}), #"Filtered Rows" = Table.SelectRows(#"Filled Down", each ([Value] <> "No" and [Value] <> "Yes")), //Remove the trailing numbers added to column names to prevent duplicate column names in original Source table #"Attribute Translation" = List.Zip({ #"Filtered Rows"[Attribute], List.Repeat(#"Base Attributes", Number.IntegerDivide(Table.RowCount(#"Filtered Rows"),6)) }), #"Rename Attributes" = Table.TransformColumns(#"Filtered Rows",{ {"Attribute", (x)=> List.Select(#"Attribute Translation", each _{0}=x){0}{1}} }), //Group and then Pivot each subgroup #"Grouped Rows" = Table.Group(#"Rename Attributes", {"Month", "Place", "Profession"}, { {"Pivot", each Table.Pivot(_, [Attribute], "Attribute","Value")}}), #"Expanded Pivot" = Table.ExpandTableColumn(#"Grouped Rows", "Pivot", #"Base Attributes"), #"Changed Type" = Table.TransformColumnTypes(#"Expanded Pivot", List.Zip({Table.ColumnNames(#"Expanded Pivot"), List.Repeat({type text},3) & List.Repeat({Int64.Type},6)})) in #"Changed Type"Results
Second Table
let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content], #"Month/Place/Profession" = List.Alternate(Table.ColumnNames(Source),6,1,3), #"Base Attributes" = List.FirstN(List.RemoveFirstN(Table.ColumnNames(Source),3),6), #"Replace Null with 0" = Table.ReplaceValue(Source,null,0,Replacer.ReplaceValue,List.RemoveMatchingItems(Table.ColumnNames(Source),#"Month/Place/Profession")), unPivot = Table.UnpivotOtherColumns(#"Replace Null with 0", {"Month","Place"},"Attribute","Value"), #"Added Custom" = Table.AddColumn(unPivot, "Profession", each if [Value]="Yes" or [Value]="No" then [Attribute] else null), #"Filled Down" = Table.FillDown(#"Added Custom",{"Profession"}), #"Filtered Rows" = Table.SelectRows(#"Filled Down", each ([Value] <> "No" and [Value] <> "Yes")), #"Add Sex" = Table.AddColumn(#"Filtered Rows","Sex", each if Text.Contains([Attribute],"Girl") or Text.Contains([Attribute],"Women") then "F" else "M",type text), #"Add Age" = Table.AddColumn(#"Add Sex", "Age", each if Text.Contains([Attribute], "<") then "0-17" else if Text.Contains([Attribute],"Elderly") then "60+" else "18-59", type text ), #"Removed Columns" = Table.RemoveColumns(#"Add Age",{"Attribute"}), #"Grouped Rows" = Table.Group(#"Removed Columns", {"Month", "Place", "Profession", "Sex", "Age"}, {{"Number", each List.Sum([Value]), type number}}) in #"Grouped Rows"2nd table results, filtered to show only January / Place A / Engineer
- 2 years ago
Hi enoch99, due to ronrsnfld provided sample data in usable format I've played with it for a while. It was a good practice with list transformations 😉
Task1 Result
let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45W8krMK00sqlTSUQrISUxOVXAEsiJTi4GkERAbALEhEJtAaUO4rAGSLEilMZSGyMJEYTIgvqlSrA6mfU5All8+koHoGNU6AzRDEdYZQ51pArZKR8kMbJ1balIRDv8hG2eIxCfRNYiAiI0FAA==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Month = _t, Place = _t, Engineer = _t, #"Girls<17" = _t, #"Boys <17" = _t, #"Women Adult" = _t, #"Men Adult" = _t, #"Elderly Women" = _t, #"Elderly Men" = _t, Doctor = _t, #"Girls<172" = _t, #"Boys <173" = _t, #"Women Adult4" = _t, #"Men Adult5" = _t, #"Elderly Women6" = _t, #"Elderly Men7" = _t, Teacher = _t, #"Girls<178" = _t, #"Boys <179" = _t, #"Women Adult10" = _t, #"Men Adult11" = _t, #"Elderly Women12" = _t, #"Elderly Men13" = _t]), ColNames = Table.ColumnNames(Source), Professions = List.Repeat(List.Alternate(List.Skip(Table.ColumnNames(Source), 2),6,1,1), Table.RowCount(Source)), Transform = List.TransformMany(Table.ToRows(Source), each List.Transform(List.Split(List.Skip(_, 2), 7), List.Skip), (x,y)=> {x{0}} & {x{1}} & y ), ListRowsToListColumns = Table.ToColumns(Table.FromRows(Transform)), ToTable = Table.FromColumns(List.FirstN(ListRowsToListColumns, 2) & {Professions} & List.Range(ListRowsToListColumns, 2), List.FirstN(ColNames, 2) & {"Professions"} & List.Range(ColNames, 3, 6)), ChangedType = Table.TransformColumnTypes(ToTable,{{"Month", type text}, {"Place", type text}, {"Professions", type text}, {"Girls<17", Int64.Type}, {"Boys <17", Int64.Type}, {"Women Adult", Int64.Type}, {"Men Adult", Int64.Type}, {"Elderly Women", Int64.Type}, {"Elderly Men", Int64.Type}}) in ChangedTypeTask2 Result
let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45W8krMK00sqlTSUQrISUxOVXAEsiJTi4GkERAbALEhEJtAaUO4rAGSLEilMZSGyMJEYTIgvqlSrA6mfU5All8+koHoGNU6AzRDEdYZQ51pArZKR8kMbJ1balIRDv8hG2eIxCfRNYiAiI0FAA==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Month = _t, Place = _t, Engineer = _t, #"Girls<17" = _t, #"Boys <17" = _t, #"Women Adult" = _t, #"Men Adult" = _t, #"Elderly Women" = _t, #"Elderly Men" = _t, Doctor = _t, #"Girls<172" = _t, #"Boys <173" = _t, #"Women Adult4" = _t, #"Men Adult5" = _t, #"Elderly Women6" = _t, #"Elderly Men7" = _t, Teacher = _t, #"Girls<178" = _t, #"Boys <179" = _t, #"Women Adult10" = _t, #"Men Adult11" = _t, #"Elderly Women12" = _t, #"Elderly Men13" = _t]), ColNames = Table.ColumnNames(Source), ProfessionsSexAge = [ a = List.Alternate(List.Skip(ColNames,2),6,1,1), //Professions b = List.Alternate(List.Skip(ColNames,2),1,6), //Repeated columns c = List.Count(b) / List.Count(a), //Count for repeat d = List.Combine(List.Transform(a, each List.Repeat({_}, c))), //Final Professions List //e = Table.AddColumn(Table.FromList(b), "Sex", each if Text.Contains([Column1], "Women", Comparer.OrdinalIgnoreCase) or Text.Contains([Column1], "Girl", Comparer.OrdinalIgnoreCase) then "F" else "M"), //Add Sex //f = Table.AddColumn(e, "Age", each if List.Contains({"G", "B"}, Text.Start([Column1],1), Comparer.OrdinalIgnoreCase) then "0-17" else if Text.StartsWith([Column1], "E", Comparer.OrdinalIgnoreCase) then "60+" else "18-59"), //Add Age //g = Table.ToList(Table.CombineColumns(Table.RemoveColumns(f, {"Column1"}) ,{"Sex", "Age"},Combiner.CombineTextByDelimiter("||", QuoteStyle.None),"Merged")), //Sex and Age as merged list //h = List.Transform(List.Zip({ d, g }), each Text.Combine(_, "||")), //Final merged list: Profession || Sex || Age i = List.Repeat({"F","M"}, List.Count(b) / 2), //Sex list j = List.Repeat({"0-17", "0-17", "18-59", "18-59", "60+", "60+"},3), //Age list k = List.Transform(List.Zip({ d, i, j }), each Text.Combine(_, "||")) //Final merged list: Profession || Sex || Age (Same as step h, but faster) ][b], Transform = List.TransformMany(Table.ToRows(Source), each {{List.Alternate(List.Skip(_,2),1,6)}}, (x,y)=> {x{0}} & {x{1}} & y ), ToTable = Table.FromRows(Transform), TransformColumn3 = Table.TransformColumns(ToTable, {{"Column3", each List.Transform(List.Zip({ ProfessionsSexAge, _ }), (x)=> Text.Combine(x, "||")), type list}}), ExpandedColumn3 = Table.ExpandListColumn(TransformColumn3, "Column3"), SplitColumnByDelimiter = Table.SplitColumn(ExpandedColumn3, "Column3", Splitter.SplitTextByDelimiter("||", QuoteStyle.Csv), {"Column3.1", "Column3.2", "Column3.3", "Column3.4"}), RenamedColumns = Table.RenameColumns(SplitColumnByDelimiter,{{"Column1", "Month"}, {"Column2", "Place"}, {"Column3.1", "Profession"}, {"Column3.2", "Sex"}, {"Column3.3", "Age"}, {"Column3.4", "Number"}}), ChangedType = Table.TransformColumnTypes(RenamedColumns,{{"Month", type text}, {"Place", type text}, {"Profession", type text}, {"Sex", type text}, {"Age", type text}, {"Number", Int64.Type}}) in ChangedType
ronrsnfld
2 years agoSuper User
To create the first table:
Data
| Month | Place | Engineer | Girls<17 | Boys <17 | Women Adult | Men Adult | Elderly Women | Elderly Men | Doctor | Girls<172 | Boys <173 | Women Adult4 | Men Adult5 | Elderly Women6 | Elderly Men7 | Teacher | Girls<178 | Boys <179 | Women Adult10 | Men Adult11 | Elderly Women12 | Elderly Men13 |
| January | Place A | Yes | 2 | 0 | 1 | 4 | 1 | 1 | Yes | 0 | 0 | 1 | 2 | 3 | 2 | Yes | 1 | 2 | 2 | 3 | 1 | 5 |
| January | Place B | No | 0 | 0 | 0 | 0 | 0 | 0 | Yes | 0 | 0 | 0 | 2 | 3 | 1 | Yes | 1 | 3 | 4 | 4 | 5 | 6 |
| February | Place A | Yes | 0 | 0 | 2 | 1 | 0 | 0 | No | 0 | 0 | 0 | 0 | 0 | 0 | Yes | 0 | 0 | 0 | 0 | 0 | 1 |
let
//Change next line to reflect your actual data source
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Month/Place/Profession" = List.Alternate(Table.ColumnNames(Source),6,1,3),
#"Base Attributes" = List.FirstN(List.RemoveFirstN(Table.ColumnNames(Source),3),6),
//Replace nulls with 0's to retain all rows when we unpivot
#"Replace Null with 0" = Table.ReplaceValue(Source,null,0,
Replacer.ReplaceValue,List.RemoveMatchingItems(Table.ColumnNames(Source),#"Month/Place/Profession")),
unPivot = Table.UnpivotOtherColumns(#"Replace Null with 0", {"Month","Place"},"Attribute","Value"),
//Add column just for Professions
#"Added Custom" = Table.AddColumn(unPivot, "Profession", each if [Value]="Yes" or [Value]="No" then [Attribute] else null),
#"Filled Down" = Table.FillDown(#"Added Custom",{"Profession"}),
#"Filtered Rows" = Table.SelectRows(#"Filled Down", each ([Value] <> "No" and [Value] <> "Yes")),
//Remove the trailing numbers added to column names to prevent duplicate column names in original Source table
#"Attribute Translation" = List.Zip({
#"Filtered Rows"[Attribute],
List.Repeat(#"Base Attributes", Number.IntegerDivide(Table.RowCount(#"Filtered Rows"),6))
}),
#"Rename Attributes" = Table.TransformColumns(#"Filtered Rows",{
{"Attribute", (x)=> List.Select(#"Attribute Translation", each _{0}=x){0}{1}}
}),
//Group and then Pivot each subgroup
#"Grouped Rows" = Table.Group(#"Rename Attributes", {"Month", "Place", "Profession"}, {
{"Pivot", each Table.Pivot(_, [Attribute], "Attribute","Value")}}),
#"Expanded Pivot" = Table.ExpandTableColumn(#"Grouped Rows", "Pivot", #"Base Attributes"),
#"Changed Type" = Table.TransformColumnTypes(#"Expanded Pivot",
List.Zip({Table.ColumnNames(#"Expanded Pivot"), List.Repeat({type text},3) & List.Repeat({Int64.Type},6)}))
in
#"Changed Type"
Results
Second Table
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Month/Place/Profession" = List.Alternate(Table.ColumnNames(Source),6,1,3),
#"Base Attributes" = List.FirstN(List.RemoveFirstN(Table.ColumnNames(Source),3),6),
#"Replace Null with 0" = Table.ReplaceValue(Source,null,0,Replacer.ReplaceValue,List.RemoveMatchingItems(Table.ColumnNames(Source),#"Month/Place/Profession")),
unPivot = Table.UnpivotOtherColumns(#"Replace Null with 0", {"Month","Place"},"Attribute","Value"),
#"Added Custom" = Table.AddColumn(unPivot, "Profession", each if [Value]="Yes" or [Value]="No" then [Attribute] else null),
#"Filled Down" = Table.FillDown(#"Added Custom",{"Profession"}),
#"Filtered Rows" = Table.SelectRows(#"Filled Down", each ([Value] <> "No" and [Value] <> "Yes")),
#"Add Sex" = Table.AddColumn(#"Filtered Rows","Sex", each if
Text.Contains([Attribute],"Girl") or Text.Contains([Attribute],"Women") then "F" else "M",type text),
#"Add Age" = Table.AddColumn(#"Add Sex", "Age", each
if Text.Contains([Attribute], "<") then "0-17"
else if Text.Contains([Attribute],"Elderly") then "60+"
else "18-59", type text ),
#"Removed Columns" = Table.RemoveColumns(#"Add Age",{"Attribute"}),
#"Grouped Rows" = Table.Group(#"Removed Columns", {"Month", "Place", "Profession", "Sex", "Age"}, {{"Number", each List.Sum([Value]), type number}})
in
#"Grouped Rows"
2nd table results, filtered to show only January / Place A / Engineer