How to calculate average weekly active visitor using DAX in PowerBI - powerbi

*Take note that Visit 1 means the first visit of the day while Visit 2 means the 2nd visit for the day.
Hello everyone,
I'm trying to calculate average weekly active visitors in PowerBI using DAX.
First, I need to calculate how many unique visitors visit the shop in one week (Mon-Sun). Based on the calendar, 5/10/2022 - 5/13/2022 will be categorized under one week, and 5/16/2022 - 5/18/2022 is another week. So for the week from 5/10/2022 - 5/13/2022, there are 9 unique visitor and for the week from 5/16/2022 - 5/18/2022, there are 3 unique visitors.
Once I found out the unique visitor for respective weeks, then I can get the average weekly active visitor by:
(9+3)/2 = 6 visitors
Hence, the answer for the example in the screenshot will be 6 visitors. The output will be used in card visualization.
Struggling to find the best way to do this, any help or advise will be greatly appreciated!
Sample Data:
https://docs.google.com/spreadsheets/d/10TsJUy-Lkdpb9Eeh5itx-XE59hytC_i5I_6UeLLHS84/edit#gid=0

I don't know enough about DAX (or Power BI) to devise a DAX only solution.
However, you can calculate the Distinct Visitors per week using Power Query M Code (Home=>Transform in Power BI), and then create a Measure to show the Average visitors per week on the card.
Power Query M Code
Edit: Change from computing weeknumber to computing start of week to avoid problems if dates span more than a year, per comment below by #weizer
let
//change next line to whatever your actual source is
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
//Don't need this column for the output
#"Removed Columns" = Table.RemoveColumns(Source,{"Visit"}),
//Set data types
#"Changed Type" = Table.TransformColumnTypes(#"Removed Columns",{{"Visitor ID", Int64.Type}, {"Date", type date}}),
//add custom column referenced to "StartOfWeek" so we can group by week
#"Added Custom" = Table.AddColumn(#"Changed Type", "WeekNumber", each Date.StartOfWeek([Date],Day.Monday), type date),
//Group by week number
// Then aggregate by week range and distinct visitor count
#"Grouped Rows" = Table.Group(#"Added Custom", {"WeekNumber"}, {
{"Date Range", each Date.ToText(List.Min([Date])) & " - " & Date.ToText(List.Max([Date])), type text},
{"Distinct Visitors", each List.Count(List.Distinct([Visitor ID])), Int64.Type}
}),
//Remove unneeded Weeknumber column
#"Removed Columns1" = Table.RemoveColumns(#"Grouped Rows",{"WeekNumber"})
in
#"Removed Columns1"
The Measure for the card will be just a simple Average function:
Distinct Visitors per Week = Average(yourTableName[Distinct Visitors])

VAR days =
SUMMARIZE(
'Sheet1'
,'Sheet1'[Date]
)
VAR Calend=
ADDCOLUMNS(
days
,"week",WEEKNUM('Sheet1'[Date])
)
VAR weeks=
SUMMARIZE(
Calend
,[week]
,"qty",COUNTROWS(VALUES('Sheet1'[Visitor ID]))
)
RETURN
AVERAGEX(
weeks
,[qty]
)

Related

7 day rolling sum not working on Power BI

I need your help. I'm working on a Power BI project and I'd like to create a Measure that calculates the 7 day rolling sum of my number of sales.
I have a table with several columns. In one of these columns, I have the number of sales per day.
My DAX measure is supposed to sum the number of sales for the day and the 6 days before. And this process is repeated for each date.
The problem is that my code doesn't work. Here's what I have:
Actual Orders - 7DR =
VAR CurrentRow = SELECTEDVALUE(Table[Date])
RETURN
CALCULATE(SUM(Table[Sales]), DATESINPERIOD(Table[Date], CurrentRow, -6, DAY))
The problem is that I also have an Excel spreadsheet with the same calculations made with a simple SUM and my results are not the same.
Do you guys have any idea why it's not working?
Thank you.
Other than perhaps an off-by-one error, that measure looks fine. With this table
let
Days = List.Dates(#date(2023,1,1),20,#duration(1, 0, 0, 0)),
#"Converted to Table" = Table.FromList(Days, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Renamed Columns" = Table.RenameColumns(#"Converted to Table",{{"Column1", "Date"}}),
#"Inserted Month" = Table.AddColumn(#"Renamed Columns", "Sales", each 1, Int64.Type),
#"Changed Type" = Table.TransformColumnTypes(#"Inserted Month",{{"Date", type date}})
in
#"Changed Type"
and this measure
Actual Orders - 7DR =
VAR CurrentRow = SELECTEDVALUE('Table'[Date])
RETURN
CALCULATE(SUM('Table'[Sales]), DATESINPERIOD('Table'[Date], CurrentRow, -7, DAY))
You get this
Check this one out:
7 day rolling sum =
VAR __LAST_DATE =
LASTDATE('Table'[Date])
RETURN
CALCULATE(
SUM('Table'[Sales]),
DATESBETWEEN('Table'[Date], DATEADD(__LAST_DATE, -6, DAY), __LAST_DATE)
)

In a matrix table in Power BI, how to make sure that the table doesn't calculate subtotals and totals for duplicates?

I have a matrix table in Power BI where the lowest heirarchy has 2 users with same product but for their manager, it needs to be only counted once. How can I do that in the matrix table?
When I was pulling the heirarchy from one table and sales from another, Power Bi was doing it on it's own but when sales is in the same table as the user heirarchy, it is simply taking a sum of all the sales when it should only sum once for cases when product is repeated for multiple users for the same manager.
As seen in the image, manager's total should be 300 but Power BI sums it up to 400. How can I make sure that manager's total is taken as 300? I'd really appreciate any help. Thank you
Simply put, you should remove the duplicate items related to manager "A" in the "Product" column. In the real scenario, you need to filter this way for each manager.
You can do this within Power Query:
(notice the table name 'SalesTable')
let
Source = Excel.CurrentWorkbook(){[Name="SalesTable"]}[Content],
#"Filtered Rows" = Table.SelectRows(Source, each [Manager] = "A"),
#"Changed Type" = Table.TransformColumnTypes(#"Filtered Rows",{{"Manager", type text}, {"User", type text}, {"Product", Int64.Type}, {"Sales", Int64.Type}}),
#"Duplicate Removed" = Table.Distinct(#"Changed Type", {"Product"}),
Sales = #"Duplicate Removed"[Sales],
CustomSUM = List.Sum(Sales)
in
CustomSUM

PowerBI DAX Create Table of Hours from Project List and Start of Week Table

I am trying to create a new table that contains a column with start of week and the hours estimated to be spent for that week on a per project basis.
Start of Week
Project
Hours
6/20/2022
ABC_XXX
10
6/27/2022
ABC_XXX
10
6/20/2022
ABC_YYY
40
6/27/2022
ABC_YYY
40
I have a table of dates representing the start of week for every project in the project table.
week start date = [date]-weekday([date],2)+1
Start of Week
6/20/2022
6/27/2022
7/4/2022
The project table contains (among other things) the project name, estimated start date, duration, and hours per week.
Project Name
Estimated Start Date
Duration in weeks
Hours Per Week
ABC_XXX
6/13/2022
8
10
ABC_YYY
6/04/2022
27
40
I am having trouble getting off the starting line. I know I need to evaluate on a per project basis and loop through all of the dates in my date table but can't find a good method to start with. I have done a lot of more simple things with creating new tables and calculations but this one is a little more complicated for me to get started. Any advice would be greatly appreciated.
The ultimate goal for this data is to present a trend showing estimated project demand over time that can be filtered by project or summed across all projects as well as filtered by timeline and displayed in a calendar view but it all starts with getting the data into this format I believe.
Here's a Power Query solution. The steps in the code below are:
use Date.AddWeeks to calculate the end date
List dates between two dates
Expand the list of dates and convert to date format
Use Date.DayOfWeek to create a day of week column
filter the table for day of week = 1 to include only weekly values (starting on Monday)
.
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WcnRyjo+IiFDSUTLTNzTWNzIwMgKyLYDY0EApVgeiIDIyEqzABCZvZA4kTBAKoqKigALmCAVAOaAqpdhYAA==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Project Name" = _t, #"Estimated Start Date" = _t, #"Duration in weeks" = _t, #"Hours Per Week" = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Project Name", type text}, {"Estimated Start Date", type date}, {"Duration in weeks", Int64.Type}, {"Hours Per Week", Int64.Type}}),
#"Added Custom1" = Table.AddColumn(#"Changed Type", "Estimated End Date", each Date.AddWeeks([Estimated Start Date],[Duration in weeks])),
#"Added Custom" = Table.AddColumn(#"Added Custom1", "dates", each {Number.From([Estimated Start Date])..Number.From([Estimated End Date])}),
#"Expanded Custom" = Table.ExpandListColumn(#"Added Custom", "dates"),
#"Changed Type1" = Table.TransformColumnTypes(#"Expanded Custom",{{"dates", type date}}),
#"Added Custom4" = Table.AddColumn(#"Changed Type1", "day of week", each Date.DayOfWeek([dates])),
#"Filtered Rows" = Table.SelectRows(#"Added Custom4", each ([day of week] = 1))
in
#"Filtered Rows"

Actual Vs Plan in PowerBI

I am having a problem in PowerBi, where I want to get results for Actual vs Plan. I have 3 tables , Book Sales Table, Plan table and Titles table. I would like the result as in Desired Output table.
Book Sales
Titles
Plan
Desired Output
You can do this in Power Query M Code
Join the Sales and Titles tables to extract the publishing unit for each book type
Add a column representing the start of each month for each sales number
Group by BOM and Unit and aggregage with Sum in case you have multiple sales/unit in a month
Join this last table with the Plan table based on Unit and Date
M Code
let
//Join the Sales and Titles to get the Publishing units
Source = Table.NestedJoin(#"Book Sales", {"Book ID"}, Titles, {"Book Id"}, "Titles", JoinKind.LeftOuter),
#"Expanded Titles" = Table.ExpandTableColumn(Source, "Titles", {"Publishing Unit"}, {"Publishing Unit"}),
//add start of month column to merge with Plan
bom = Table.AddColumn(#"Expanded Titles", "BOM", each Date.StartOfMonth([Invoice Date]),type date),
//Group by unit and bom columns in case you happen to have multiple sales in the same month
#"Grouped Rows" = Table.Group(bom, {"Publishing Unit", "BOM"}, {{"Sales amount", each List.Sum([Sales amount]), type number}}),
//Join with Plan using bom and date as the key
salesVplan = Table.NestedJoin(Plan,{"Business Unit","Date"}, #"Grouped Rows", {"Publishing Unit","BOM"},"joined",JoinKind.FullOuter),
#"Expanded joined" = Table.ExpandTableColumn(salesVplan, "joined", {"Sales amount"}, {"Sales amount"})
in
#"Expanded joined"
This could be done in several different ways, but I would recommend doing this in SQL personally. This means that you can:
Select from all the tables you want to show, into the same table. Lets call it Products.
Then you join in the values that you want on that.
This way, there is no dax calculation that takes time, but rather just something that takes time while you refresh the dataset itself.

Combine real and planned data in PowerBI KPI visualizations

I've got two primary datasets:
Real data with all sales transactions.
For example RealData:
Date;Sales
16-01-2017;1200
20-01-2017;1500
05-02-2017;800
08-02-2017;1100
13-02-2017;300
Etc.
A plan with total sales I want to achieve, with totals at the last day of each month.
For example EndOfMonthTargets:
Date;Sales
31-01-2017;3000
28-02-2017;2500
Etc.
In my real data I (a) also have data from the years before 2017, and obviously I have the targets for each month in 2017. The RealData is always live / up to date.
What I'm trying to do is show KPI visualizations: how is the real data vs the plan doing. However, I can't figure out how to relate the two datasets, because the cannot really be joined together.
What is the idiomatic way to do this in PowerBI?
I've tried:
adding a column to each source with its respective status ("real" vs "plan")
creating a union (i.e. "Append Queries as New")
adding a column Month = MONTH([Date])
Giving me this data:
But that's weird, because then the KPI visualization will include the "Plan" data either at the start or worse at the end where it will be plotted as the "current" number.
The expected output is a KPI visualization:
showing the absolute number of sales summed by year (or month, if my slicers are set that way!)
with the Target goals retrieved from the plan data
with a trend based on previous years (not included in my sample data)
How do I achieve that?
There are a few ways to join tables like this. What you have are 2 tables with different granularities: a sales table that goes to the day, and a target table that goes down to the month. It's a common request to model them against each other, and it boils down to having a lookup table that both fact tables can join with.
What I would recommend:
Have a table of your real data
Have a table of your plan/target data, using the last day of the month is fine
Do not relate these 2 fact tables together directly
Rather, have a separate date lookup table, to which both tables are joined. This date dimension should, at a minimum, have a month & year column (e.g. March 2017).
Join both fact tables to your date table
Hide the date fields in your 2 fact tables, so that you aren't tempted to use them in visuals (you have to use the date fields from the lookup table instead)
You can then create measures to SUM your actual and targets. And then additional measures that subtract those 2 measures against each other (or divide one into the other). All those measures will then be sliceable by the month & year on your date table. (You could slice them by date too, but because targets are assigned to the last day of the month, that granularity will be less than helpful.)
There's a lot of good information & examples here: http://www.daxpatterns.com/handling-different-granularities/
The way I would do it:
Add a calculated column to both real and targets tables:
Month = Date(Actual[Date].[Year],Actual[Date].[MonthNo],1)
Month = Date(Target[Date].[Year],Target[Date].[MonthNo],1)
Create relashionships between these
Plot SUM(RealData[Sales]) and Target[Sales] against Target[Month]
You can use PowerQuery to transform data.
"Real" table:
let
Source = Table.FromRecords({[Date="16.01.2017", Sales = 1200], [Date="20.01.2017", Sales=1500], [Date="05.02.2017", Sales = 800], [Date="08.02.2017", Sales = 1100], [Date="13.02.2017", Sales = 300], [Date="10.01.2016", Sales = 1400], [Date="02.02.2016", Sales = 1800]}),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Date", type date}, {"Sales", Int64.Type}})
in
#"Changed Type"
"Plan" table:
let
Source = Table.FromRecords({[Date="31.01.2017", Sales = 3000], [Date="28.02.2017", Sales=2500], [Date="31.01.2016", Sales = 2800], [Date="29.02.2016", Sales = 2700]}),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Date", type date}, {"Sales", Int64.Type}})
in
#"Changed Type"
Your query for getting data, let's name it GetData:
let
t1 = Table.AddColumn(Real, "Source", each "Real"),
t2 = Table.AddColumn(Plan, "Source", each "Plan"),
MergedTable = Table.Combine({t1, t2}),
AddYear = Table.AddColumn(MergedTable, "Year", each Date.Year([Date])),
AddMonth = Table.AddColumn(AddYear, "Month", each Date.Month([Date])),
Group = Table.Group(AddMonth, {"Year", "Month", "Source"}, {{"Sales", each List.Sum([Sales]), type number}})
in
Group
You may avoid using last step by grouping results at report level, but this will result in users being able to view amount of each sale. If this is expected behavior, just remove Group step, or replace it with Table.RemoveColumn to remove [Date].
If you need separate columns for Plan and Real values, then pivot Source column.
Then just use GetData query in clustered column chart.
You will have to create a measure to calculate the Actual total and measure to calculate the Planned by each month or end of month. Then create a measure to compare the difference between Planned total and Actual total.
Actual =
CALCULATE (
SUM ( RealDate[Sales] ),
FILTER (
ALL ( RealDate ),
MONTH ( [Date] ) = MONTH ( MAX ( EndOfMonthTargets[Date] ) )
&& YEAR ( [Date] ) = YEAR ( MAX ( EndOfMonthTargets[Date] ) )
)
)
Planned = SUM(EndOfMonthTargets[Sales])
ActualVSPlanned = [Actual] - [Planned]
Now use that measures and the Date in eEndOfMonthTargets table to build a matrix:
For the ActualVSPlanned measure use conditional formating as follows:
You will get something like this: