Home > Enterprise >  Unpivot Several Columns to Result in Two
Unpivot Several Columns to Result in Two

Time:01-12

I receive data that looks like this:

Name 01/01/2023 01/02/2023 Revenue Revenue
Chris 1 3 £100 £300
Colin 5 8 £500 £800
Pete 2 5 £200 £500

Where name is self-explanatory, the next two columns are dates (in UK format) with the number of days worked in the period shown below, and the final two columns are revenue.

I want to modify this data in Power Query so it looks like this:

Name Date Work Days Revenue
Chris 01/01/2023 1 £100
Chris 01/02/2023 3 £300
Colin 01/01/2023 5 £500
Colin 01/02/2023 8 £800
Pete 01/01/2023 2 £200
Pete 01/02/2023 5 £500

I thought this would be some kind of a pivot operation but I can't figure it out.

Any assistance will be gratefully received.

Thanks,

Chris

CodePudding user response:

One simple way

let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
Set0=List.FirstN(Table.ColumnNames(Source),1),
Set1= List.Combine({Set0,List.Alternate(Table.ColumnNames(Source),1,1)}),
Set2=List.Combine({Set0,List.Alternate(List.RemoveFirstN(Table.ColumnNames(Source),1),1,1)}),
Part1 = Table.SelectColumns(Source,Set1),
Part2 = Table.SelectColumns(Source,Set2),
Date1 = Table.AddColumn(Part1,"Date" , each Table.ColumnNames(Part1){1}),
Date2 = Table.AddColumn(Part2,"Date" , each Table.ColumnNames(Part2){1}),
Rename1 = Table.RenameColumns(Date1,{{Table.ColumnNames(Part1){2}, "Revenue"}, {Table.ColumnNames(Part1){1}, "Work Days"}}),
Rename2 = Table.RenameColumns(Date2,{{Table.ColumnNames(Part2){2}, "Revenue"}, {Table.ColumnNames(Part2){1}, "Work Days"}}),
combined = Rename1 & Rename2
in combined

or

let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Added Index" = Table.AddIndexColumn(Source, "Index", 0, 1, Int64.Type),
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Added Index", {"Index", "Name"}, "Attribute", "Value"),
#"Added Custom" = Table.AddColumn(#"Unpivoted Other Columns", "Date", each if Text.Start([Attribute],3)="Rev" then null else [Attribute]),
#"Added Custom2" = Table.AddColumn(#"Added Custom", "count", each if Text.Start([Attribute],3)="Rev" then null else [Value]),
#"Added Index1" = Table.AddIndexColumn(#"Added Custom2", "Index.1", 0, 1, Int64.Type),
#"Inserted Modulo" = Table.AddColumn(#"Added Index1", "Modulo", each Number.Mod([Index.1], 2), type number),
#"Sorted Rows" = Table.Sort(#"Inserted Modulo",{{"Index", Order.Ascending}, {"Modulo", Order.Ascending}, {"Attribute", Order.Ascending}}),
#"Filled Down" = Table.FillDown(#"Sorted Rows",{"Date", "count"}),
x=Table.AlternateRows(#"Filled Down",0,1,1),
#"Removed Other Columns" = Table.SelectColumns(x,{"Name", "Value", "Date", "count"})
in  #"Removed Other Columns"

CodePudding user response:

Here's another way:

  • Using List.Generate, create a List of Tables using each Date/Revenue Pair.
  • For each of the tables, ensure the Revenue Column is named Revenue (and not Revenue2, Revenu3, etc) and then Unpivot the table.
  • Then expand the column that has the list of tables
  • The rest is "housekeeping"
let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Name", type text}, 
        {"1/1/2023", Int64.Type}, {"1/2/2023", Int64.Type}, {"Revenue", type text}, {"Revenue2", type text}}),

    #"Data Columns" = List.RemoveFirstN(Table.ColumnNames(#"Changed Type"),1),

//create a list of tables consisting of each date/revenue pair
// then unpivot each table
// ensure Revenue column has the same name throughout
    #"Data Pairs" = List.Generate(
        ()=>[t=Table.SelectColumns(#"Changed Type", {"Name",#"Data Columns"{0}, #"Data Columns"{0 List.Count(#"Data Columns")/2}}), idx=0],
            each [idx] < List.Count(#"Data Columns") / 2,
            each [t=Table.SelectColumns(#"Changed Type", {"Name",#"Data Columns"{[idx] 1}, #"Data Columns"{[idx] 1 List.Count(#"Data Columns")/2}}), idx=[idx] 1],
            each Table.Unpivot(
                    Table.RenameColumns([t], {Table.ColumnNames([t]){2},"Revenue"}),
                        {#"Data Columns"{[idx]}},"Date","Work Days")),

//to a table
//  then combine the tables with column names in desired order
    #"Converted to Table" = Table.FromList(#"Data Pairs", Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Expanded Column1" = Table.ExpandTableColumn(#"Converted to Table", "Column1", {"Name", "Date", "Work Days", "Revenue"}),

//set the data types
    #"Changed Type with Locale" = Table.TransformColumnTypes(#"Expanded Column1", {
        {"Name", type text},
        {"Date", type date},
        {"Work Days", Int64.Type},
        {"Revenue", Currency.Type}}, "en-GB"),

//Sort to desired order
    #"Sorted Rows" = Table.Sort(#"Changed Type with Locale",{{"Name", Order.Ascending}, {"Date", Order.Ascending}})
in
    #"Sorted Rows"

enter image description here

  • Related