Forum Discussion

F_Reh's avatar
F_Reh
Icon for Post Patron rankPost Patron
1 year ago
Solved

Pivoting/Unpivoting Numerator & Denominator Columns to four Month-Specific ones for recent 2 Months

Good Afternoon.

 

I have the following table in Power Query. I have restricted it only to always bring in the two most recent months, and will refresh every month to reflect this:

 

 

I desire to convert this Table to as follows:

 

 

The ultimate intention is to build two additional Calculated columns to show the differences between the two most recent months in terms of both figures (i.e. Numerator) and percentages (i.e. Numerator/Denominator). The column names must NOT be hard coded as above (Dec-24/Jan-25) but should dynamically change month-by-month.

 

I have tried varying permutations of PIVOTING/UNPIVOTING the Denominator and Numerator columns but the desired output has not yet been achieved.

 

Kindly advise.

 

 

  • Hi F_Reh , here's a solution you can try out. I'll attach the images of the output, source table and text of the M code used. Thanks!

     

    Here's the code used in Advanced Editor:

    let


    Source = Excel.CurrentWorkbook(){[Name="Table4"]}[Content],


    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Month_Year", type date}, {"Numerator", Int64.Type}, {"Denominator", Int64.Type}}),


    Dates = Table.TransformColumns(#"Changed Type",{"Month_Year", each Date.ToText(_,"MMM - yy")}),


    ColNames = List.Skip(Table.ColumnNames(Dates)),


    Date = Table.FromList(List.Distinct(Dates[Month_Year])),


    Custom = Table.AddColumn(Date, "Custom", each ColNames),


    Expand = Table.ExpandListColumn(Custom, "Custom"),


    Merge = Table.CombineColumns(Expand,{"Column1", "Custom"},Combiner.CombineTextByDelimiter(" ", QuoteStyle.None),"ColumnNames")[ColumnNames],


    List = Table.Group(Dates,{"Month_Year"},{{"Cols", each _[[Numerator],[Denominator]]}})[Cols],


    Table = Table.FromColumns(List.Combine(List.Transform(List, each Table.ToColumns(_))),Merge)


    in


    Table

  • Here is another M-Code solution. It involves unpivoting, sorting, merging columns and pivoting.

    Please read the code comments to best understand the algorithm.

    let
        Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("XY69CsMwDITfxXMCsuK/zi0dMpQO3UwGUwwNDQk4pc9fy0lN7EUH+nS6s5bd/ccH1rCOizQxzt7NLUo2NJb14zTFDVfKkHAwJb8GN7/jSksyalQlPr/CuJIRQW0iyoNH8N8l5Z8kve46Vb24LcGRNeVXLJcXCkjA0PuLf7Yoivpis4OGkv/r77iEuTwgJklXh4NcXiMRzav0vTpqkSYe6PAD", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Name = _t, Denominator = _t, Numerator = _t, Month_Year = _t]),
        #"Changed Type" = Table.TransformColumnTypes(Source,{
            {"Name", type text}, {"Denominator", Int64.Type}, {"Numerator", Int64.Type}, {"Month_Year", type text}}),
    
    //Add real date column to enable proper sorting
    //then sort and remove the column
        #"Add Date" = Table.AddColumn(#"Changed Type","Date", (r)=>
            [a=Text.Split(r[Month_Year],"-"),
             b=Text.Combine({"20" & a{1}, a{0},"1"},"-"),
             c=Date.From(b)][c], type date),
        #"Sorted Rows" = Table.Sort(#"Add Date",{{"Date", Order.Ascending}}),
        #"Removed Columns" = Table.RemoveColumns(#"Sorted Rows",{"Date"}),
    
    //Unpivot the Denominator/Numerator columns
        #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Removed Columns", {"Month_Year", "Name"}, "Attribute", "Value"),
    
    //Merge the Attribute columns
    //Then Pivot
        #"Merged Columns" = Table.CombineColumns(#"Unpivoted Other Columns",{"Month_Year", "Attribute"},Combiner.CombineTextByDelimiter(":", QuoteStyle.None),"Merged"),
        #"Pivoted Column" = Table.Pivot(#"Merged Columns", List.Distinct(#"Merged Columns"[Merged]), "Merged", "Value", List.Sum)
    in
        #"Pivoted Column"

     Original

     

    Results

     

     

  • Hi F_Reh, another solution:

     

    Output

     

    let
        Source = Table.TransformColumnTypes(Expression.Evaluate("Table.FromRows(List.Transform(Text.Split(""Peter;314;312;Jan-25|Jill;1668;1108;Jan-25|Frank;752;726;Jan-25|Chris;1206;1204;Jan-25|Trevor;3958;3366;Jan-25|Nora;18;16;Jan-25|Peter;3460;3084;Dec-24|Jill;1418;1070;Dec-24|Frank;18;10;Dec-24|Chris;1022;1018;Dec-24|Trevor;728;714;Dec-24|Nora;274;272;Dec-24"",""|""), each Text.Split(_, "";"")), {""Name"",""Denominator"",""Numerator"",""Month_Year""})", #shared),{{"Name", type text}, {"Denominator", Int64.Type}, {"Numerator", Int64.Type}, {"Month_Year", type text}}),
        GroupedRows = Table.Group(Source, {"Name"}, {{"T", each 
            [ a = Table.Sort(_, (x)=> Date.From(x[Month_Year])),
              b = {Record.ToList(a{0}){0}} & a[Denominator] & a[Numerator],
              c = {"Name"} & List.Combine(List.Transform(a[Month_Year], each {_ &" "& "Denominator", _ &" "& "Numerator"})),
              d = Table.FromRows({b}, c)
            ][d], type table}}),
        CombinedT = Table.Combine(GroupedRows[T])
    in
        CombinedT

21 Replies