Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Compete to become Power BI Data Viz World Champion! First round ends August 18th. Get started.

Reply
rcarmichael1990
New Member

Removing Promotional Data From Sales

Good afternoon,

I have a data set in PQ which comprises of a list of dates, product codes, the sales quantity, and a flag (where an item on promotion is denoted by a number greater than 0) which shows whether the specific item was on promotion on the specific date:

DateProductSale QtyPromo Flag
22 Oct 2023Prod0180
23 Oct 2023Prod0190
24 Oct 2023Prod0140
25 Oct 2023Prod0150
26 Oct 2023Prod0190
27 Oct 2023Prod01100
28 Oct 2023Prod0180
29 Oct 2023Prod0160
30 Oct 2023Prod0150
31 Oct 2023Prod01113
1 Nov 2023Prod01176
2 Nov 2023Prod0161
3 Nov 2023Prod01194
4 Nov 2023Prod01153
5 Nov 2023Prod01145
6 Nov 2023Prod01164
7 Nov 2023Prod0120
8 Nov 2023Prod01125
9 Nov 2023Prod01224
10 Nov 2023Prod01195
11 Nov 2023Prod01275
12 Nov 2023Prod01123
13 Nov 2023Prod01304
14 Nov 2023Prod0101
15 Nov 2023Prod01124
16 Nov 2023Prod01114
17 Nov 2023Prod01225
18 Nov 2023Prod01246
19 Nov 2023Prod01173
20 Nov 2023Prod01160
21 Nov 2023Prod01100
22 Nov 2023Prod01110
23 Nov 2023Prod01130
24 Nov 2023Prod01440
25 Nov 2023Prod01780

I would like to derive baseline sales, ie replace the sales where the product was on promotion with the average of the previous non-promo qty, and next non-promo entry (preferably smoothing between them, but i'll settle for the average across each day).

 

For example, in the data set above I would have the 08 Nov through 19 Nov be the average of 2 and 16, so each of the dates between 08 Nov and 19 Nov would show 9; or even better, 8th would be 3, 9th would be 4... 18th would be 13, 19th would be 14.

 

I'm unsure of how to reference the previous & next  [Promo Flag] = 0 to average... or a better alternative.

Any assistance is greatly appreciated.

Sincere regards,

Ryan

1 ACCEPTED SOLUTION
AlienSx
Super User
Super User

let
    // duration step
    one_day = #duration(1, 0, 0, 0),
    // function to generate list of dates and sales
    calc = (x, y, n) => 
        [daily_sales = (y{1} - x{1}) / n, 
        lst = List.Zip({List.Dates(x{0} + one_day, n - 1, one_day), List.Numbers(x{1} + daily_sales, n - 1, daily_sales)})][lst],
    // Source data - replac with yours
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    tp = Table.TransformColumnTypes(Source,{{"Date", type date}}),
    // filter out promo sales and get list from table
    nopromo_table = Table.SelectRows(tp, (x) => x[Promo Flag] = 0),
    nopromo = List.Buffer(Table.ToList(nopromo_table, (x) => {x{0}, x{2}})),
    // generate list of missing dates and sales 
    generate = List.Generate(
        () => [i = 0, s = nopromo{0}, n = 0, res = {}],
        (x) => x[i] < List.Count(nopromo),
        (x) => 
            [
                i = x[i] + 1, 
                s = nopromo{i}, 
                n = Duration.Days(s{0} - x[s]{0}), 
                res = if n <= 1 then {} else calc(x[s], s, n)
            ],
        (x) => x[res]
    ), 
    // generated list >> to table
    baseline_sales = Table.FromList(List.Combine(generate), (x) => x, {"Date", "Sale Qty"}),
    // combine and sort new sales table, fill down product column
    all = Table.Sort(nopromo_table & baseline_sales, "Date"), 
    fd = Table.FillDown(all, {"Product"})
in
    fd

sssls.jpg

 

View solution in original post

4 REPLIES 4
AlienSx
Super User
Super User

let
    // duration step
    one_day = #duration(1, 0, 0, 0),
    // function to generate list of dates and sales
    calc = (x, y, n) => 
        [daily_sales = (y{1} - x{1}) / n, 
        lst = List.Zip({List.Dates(x{0} + one_day, n - 1, one_day), List.Numbers(x{1} + daily_sales, n - 1, daily_sales)})][lst],
    // Source data - replac with yours
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    tp = Table.TransformColumnTypes(Source,{{"Date", type date}}),
    // filter out promo sales and get list from table
    nopromo_table = Table.SelectRows(tp, (x) => x[Promo Flag] = 0),
    nopromo = List.Buffer(Table.ToList(nopromo_table, (x) => {x{0}, x{2}})),
    // generate list of missing dates and sales 
    generate = List.Generate(
        () => [i = 0, s = nopromo{0}, n = 0, res = {}],
        (x) => x[i] < List.Count(nopromo),
        (x) => 
            [
                i = x[i] + 1, 
                s = nopromo{i}, 
                n = Duration.Days(s{0} - x[s]{0}), 
                res = if n <= 1 then {} else calc(x[s], s, n)
            ],
        (x) => x[res]
    ), 
    // generated list >> to table
    baseline_sales = Table.FromList(List.Combine(generate), (x) => x, {"Date", "Sale Qty"}),
    // combine and sort new sales table, fill down product column
    all = Table.Sort(nopromo_table & baseline_sales, "Date"), 
    fd = Table.FillDown(all, {"Product"})
in
    fd

sssls.jpg

 

Thank you! I'll need to read through it a few more times to understand how you acomplished some of the steps.

bhanu_gautam
Super User
Super User

@rcarmichael1990 , 

Here’s a step-by-step guide:

Create a Calculated Column for Non-Promo Sales: First, create a calculated column that only includes sales quantities for non-promotion days. This will help in identifying the previous and next non-promotion sales quantities.
NonPromoSales = IF('Table'[Promo Flag] = 0, 'Table'[Sale Qty], BLANK())


Create a Calculated Column for Previous Non-Promo Sales: Create a calculated column to get the previous non-promotion sales quantity.

PreviousNonPromoSales =
VAR CurrentDate = 'Table'[Date]
RETURN
CALCULATE(
MAX('Table'[NonPromoSales]),
FILTER(
'Table',
'Table'[Date] < CurrentDate && NOT(ISBLANK('Table'[NonPromoSales]))
)

 

Create a Calculated Column for Next Non-Promo Sales: Create a calculated column to get the next non-promotion sales quantity.
NextNonPromoSales =
VAR CurrentDate = 'Table'[Date]
RETURN
CALCULATE(
MIN('Table'[NonPromoSales]),
FILTER(
'Table',
'Table'[Date] > CurrentDate && NOT(ISBLANK('Table'[NonPromoSales]))
)

 

Create a Calculated Column for Baseline Sales: Finally, create a calculated column that calculates the baseline sales by averaging the previous and next non-promotion sales quantities.
BaselineSales =
IF(
'Table'[Promo Flag] > 0,
DIVIDE('Table'[PreviousNonPromoSales] + 'Table'[NextNonPromoSales], 2),
'Table'[Sale Qty]
)




Did I answer your question? Mark my post as a solution! And Kudos are appreciated

Proud to be a Super User!




LinkedIn






Thank you for your reply!

Unfortunately as the code wasn't what Power Query accepts in the "Custom Column" dialogue, I was unable to proceed with your solution; 

ie RETURN, CALCULATE, MIN, & FILTER.

Helpful resources

Announcements
August Power BI Update Carousel

Power BI Monthly Update - August 2025

Check out the August 2025 Power BI update to learn about new features.

August 2025 community update carousel

Fabric Community Update - August 2025

Find out what's new and trending in the Fabric community.

Top Solution Authors