Walmart M5 Data Platform Step 8 report · Executive dashboard analysis
Step 08 · Data analysis

DAX catalogue, then Executive dashboard report

Part A lists all 33 Power BI DAX measures in full. Part B validates Dashboard 1 (Executive) against data/gold_export/.

Part A · 33 DAX measures Part B · Dashboard 1 analysis

Live Power BI dashboard

Published report walmart_visualization — Executive, Store, Product, and Demand pages on Gold aggregates. Open in Power BI ↗

Analysis pages: 08 Executive · 09 Store · 10 Product · 11 Demand · Overview

Part A — All DAX measures (paste into _Measures)

Complete catalogue of 33 Power BI measures used across all dashboard pages. Create each with right-click _Measures → New measure, then paste. Format currency / percentage measures in the ribbon after creating them.

Core sales

/* 1 */
Total Units =
SUM ( 'agg_daily_store_sales'[units_sold] )

/* 2 — format Currency $ */
Total Sales Value =
SUM ( 'agg_daily_store_sales'[sales_value] )

/* 3 — format Currency $ */
Avg Sell Price =
AVERAGE ( 'agg_daily_store_sales'[avg_sell_price] )

/* 4 */
Active SKUs (Store Day) =
SUM ( 'agg_daily_store_sales'[active_skus] )

/* 5 — format Currency $ */
Avg Daily Sales Value =
AVERAGEX (
    VALUES ( 'dim_date'[date] ),
    [Total Sales Value]
)

Category

/* 6 */
Category Units =
SUM ( 'agg_daily_category_sales'[units_sold] )

/* 7 — format Currency $ */
Category Sales Value =
SUM ( 'agg_daily_category_sales'[sales_value] )

/* 8 */
Category Active Stores =
SUM ( 'agg_daily_category_sales'[active_stores] )

Product performance

/* 9 */
Product Units =
SUM ( 'agg_product_performance'[units_sold] )

/* 10 — format Currency $ */
Product Sales Value =
SUM ( 'agg_product_performance'[sales_value] )

/* 11 */
Product Avg Daily Units =
AVERAGE ( 'agg_product_performance'[avg_daily_units] )

/* 12 */
Product Demand Volatility =
AVERAGE ( 'agg_product_performance'[demand_volatility] )

/* 13 — format Currency $ */
Product Avg Price =
AVERAGE ( 'agg_product_performance'[avg_sell_price] )

/* 14 */
Stores Selling =
SUM ( 'agg_product_performance'[stores_selling] )

/* 15 */
Product Units Rank =
RANKX (
    ALLSELECTED ( 'agg_product_performance'[item_id] ),
    [Product Units],
    ,
    DESC,
    DENSE
)

Demand trends

/* 16 */
Daily Units =
SUM ( 'agg_demand_trends'[daily_units] )

/* 17 — format Currency $ */
Daily Sales Value (Demand) =
SUM ( 'agg_demand_trends'[daily_sales_value] )

/* 18 */
Rolling 7D Units =
SUM ( 'agg_demand_trends'[rolling_7d_units] )

/* 19 */
Rolling 28D Units =
SUM ( 'agg_demand_trends'[rolling_28d_units] )

/* 20 */
Rolling 7D Avg Units =
AVERAGE ( 'agg_demand_trends'[rolling_7d_avg_units] )

/* 21 */
Active SKUs (Demand) =
SUM ( 'agg_demand_trends'[active_skus] )

/* 22 */
Active Stores (Demand) =
SUM ( 'agg_demand_trends'[active_stores] )

Event & price

/* 23 */
Event Units =
SUM ( 'agg_event_sales'[units_sold] )

/* 24 — format Currency $ */
Event Sales Value =
SUM ( 'agg_event_sales'[sales_value] )

/* 25 — format Percentage */
Category Share =
AVERAGE ( 'agg_store_category_sales'[category_sales_share] )

/* 26 — format Currency $ */
Price Avg =
AVERAGE ( 'agg_price_analysis'[avg_sell_price] )

/* 27 — format Currency $ */
Price Median =
AVERAGE ( 'agg_price_analysis'[median_sell_price] )

Time intelligence

Requires dim_date[date] marked as the date table.

/* 28 — format Currency $ */
Sales Value Previous Year =
CALCULATE (
    [Total Sales Value],
    SAMEPERIODLASTYEAR ( 'dim_date'[date] )
)

/* 29 — format Percentage */
Sales Value YoY % =
VAR Curr = [Total Sales Value]
VAR Prev = [Sales Value Previous Year]
RETURN
IF (
    Prev = 0 || ISBLANK ( Prev ),
    BLANK (),
    DIVIDE ( Curr - Prev, Prev )
)

/* 30 */
Units Previous Year =
CALCULATE (
    [Total Units],
    SAMEPERIODLASTYEAR ( 'dim_date'[date] )
)

/* 31 — format Percentage */
Units YoY % =
VAR Curr = [Total Units]
VAR Prev = [Units Previous Year]
RETURN
IF (
    Prev = 0 || ISBLANK ( Prev ),
    BLANK (),
    DIVIDE ( Curr - Prev, Prev )
)

/* 32 — format Currency $ */
Sales Value MTD =
TOTALMTD ( [Total Sales Value], 'dim_date'[date] )

/* 33 — format Currency $ */
Sales Value YTD =
TOTALYTD ( [Total Sales Value], 'dim_date'[date] )

Quick index

#MeasureGroupUsed on Executive?
1Total UnitsCoreYes — card
2Total Sales ValueCoreYes — card, store bar
3Avg Sell PriceCoreNo (Store page)
4Active SKUs (Store Day)CoreNo
5Avg Daily Sales ValueCoreYes — card
6Category UnitsCategoryNo
7Category Sales ValueCategoryYes — category column
8Category Active StoresCategoryNo
9–15Product *ProductNo (Product page)
16Daily UnitsDemandYes — demand line
17Daily Sales Value (Demand)DemandNo (Demand page)
18Rolling 7D UnitsDemandYes — demand line
19–22Rolling / Active *DemandNo (Demand page)
23–27Event / Price *Event / priceNo (Store / Demand / Product)
28–29Sales Value Previous Year / YoY %Time intelYes — YoY card
30–33Units YoY / MTD / YTDTime intelOptional
Part B — Dashboard 1 analysis

Executive page: validation & findings

Independent check of the Power BI Executive page against data/gold_export/. Numbers recomputed with scripts/analyze_executive_dashboard.py.

KPIs match dashboard Sales card formatted Demand line at day grain 2016 vs 2015 YTD card Window: 2011-01-29 → 2016-05-22 1,941 sales days

Dashboard 1 screenshot — Executive (updated)

Power BI page Executive after UI fixes: sales card 191.58M, daily demand + rolling 7D, five KPI cards including 2016 YTD vs 2015 YTD ≈ 18%, years 2011–2016 selected.

Power BI Executive dashboard with five KPI cards including 2016 YTD vs 2015 YTD, daily demand line, store ranking, category sales
Figure 1. Executive (updated) — 67M units · 191.58M sales · YoY 27.08% · Avg daily 98.70K · 2016 YTD vs 2015 YTD 0.18 (18%) · CA_3 / FOODS lead
Total Units
66.9M
Dashboard 67M · exact 66,927,173
Total Sales Value
$191.58M
Formatted on card as 191.58M
Avg Daily Sales
$98.7K
$98,700.44 / day
2016 vs 2015 YTD
+18%
Same-window card · gold_export match

1. Scope & method

Source tables: agg_daily_store_sales, agg_daily_category_sales, agg_demand_trends, dim_date. Facts were not required — Executive visuals are built from Gold aggregates (same design as the Power BI Import model).

Dashboard visualGold sourceValidation result
Total Units / Sales / Avg Daily cards agg_daily_store_sales Exact match
Sales Value YoY % Store sales + dim_date LY shift ~27–28% (SAMEPERIODLASTYEAR behaviour)
Demand line (by date) agg_demand_trends Day grain fixed — daily + rolling 7D visible
Sales by store agg_daily_store_sales CA_3 → CA_4 order matches
Sales by category agg_daily_category_sales FOODS $111M · HOUSEHOLD $57M · HOBBIES $23M

2. Visualization & interaction (Dashboard 1 — Executive)

The Executive page is designed as a single-screen overview: KPI strip → demand trend → store and category breakdown. Interaction is driven by the year slicer, visual highlighting, and the star-schema filter path (dim_date / dim_store → aggregates → measures).

2.1 Page layout (information hierarchy)

┌─────────────────────────────────────────────────────────────┐
│  [ Year slicer ]                                            │
│  [ Total Units ] [ Sales $ ] [ YoY % ] [ Avg Daily Sales ]  │
│  [──────── Demand line: daily vs rolling 7D (wide) ───────] │
│  [ Store ranking bar (left) ] [ Category columns (right) ]  │
└─────────────────────────────────────────────────────────────┘
ZonePurposeWhy this visual
Top — slicer Time context for the whole page Year is the natural planning grain for executives
KPI cards Answer “how big / how growing?” in one glance Cards minimise cognitive load; 4 measures max
Wide line chart Show demand trajectory and smoothing Line encodes time; dual series contrasts noise vs trend
Store bar Rank outlets by revenue Horizontal bar is best for long category labels (store_id)
Category column Show mix (FOODS / HOUSEHOLD / HOBBIES) Few categories → clustered column reads clearly

2.2 Visual-to-field map

VisualTypeFields / measuresInteraction notes
Year Slicer dim_date[year] Primary filter; sync to other pages via Sync slicers
Total Units Card [Total Units] Responds to year (and cross-highlight from other visuals)
Total Sales Value Card [Total Sales Value] Format as Currency; avoid raw long decimals
Sales Value YoY % Card [Sales Value YoY %] Needs date table; blank if no prior-year overlap
Avg Daily Sales Value Card [Avg Daily Sales Value] More robust than annual totals for partial years
Demand trend Line X agg_demand_trends[date]; Y [Daily Units], [Rolling 7D Units] (or columns) Use continuous date, not Year hierarchy, for daily grain
Sales by store Clustered bar Y dim_store[store_id]; X [Total Sales Value] Sort descending; click a store to highlight / filter other visuals
Sales by category Clustered column X agg_daily_category_sales[cat_id]; Y [Category Sales Value] Click FOODS / HOUSEHOLD / HOBBIES to filter store + cards

2.3 Interaction design

InteractionHow it works on ExecutiveUser value
Year slicer filter Selecting one or more years filters all visuals that depend on dim_date (cards, demand line, store/category charts via related date keys on aggs). Compare a single year or multi-year window without rebuilding the page
Cross-filtering / highlight Clicking a store bar or category column filters other visuals (default Power BI edit interactions: Filter). Example: click CA_3 → cards and category chart recompute for that store where relationships allow. Drill from overview → outlet or category without leaving the page
Edit interactions Format → Edit interactions: set whether a visual Filters, Highlights, or None on peers. Recommended: slicer → Filter all; category/store → Filter cards + peer chart; keep demand line as Filter from year only if category grain does not map cleanly. Prevent confusing blank charts when grains do not align
Sync slicers View → Sync slicers: sync year to Store / Product / Demand pages so the same time window follows the analyst across the report. Consistent storytelling across the four-page workbook
Tooltips Default tooltips show series name + value on hover. Optional: add state_id or avg_sell_price as tooltip fields on the store bar. Extra context without cluttering the canvas
Drill on date axis If X-axis uses Date Hierarchy, users can drill Year → Quarter → Month → Day. Prefer plain date for demand so daily seasonality (weekends, Christmas) stays visible. Avoid accidental year roll-ups that hide calendar effects
Sort & legend Store bar sorted by sales descending; demand legend distinguishes daily vs rolling 7D. Ranking and trend comparison without extra clicks

2.4 Model rules that enable interaction

2.5 Suggested analyst click-path

  1. Set year slicer to a full year (e.g. 2015) for clean totals.
  2. Read the four KPI cards (size, growth, daily run-rate).
  3. Scan the demand line for trend / seasonality (use day grain).
  4. Click top store (CA_3) → see how category mix and KPIs shift.
  5. Clear selection → click FOODS → see store ranking under that category.
  6. Move to Store / Product / Demand pages with synced year for deeper detail.

2.6 Visualization caveats (interaction + interpretation)

3. Key pattern findings

3.1 Incomplete years distort annual totals (critical)

Training sales run 2011-01-29 → 2016-05-22. 2011 has 337 days; 2016 has only 143 days (through 22 May). Full calendar years are 2012–2015 only.

YearDaysTotal units Avg daily unitsSales value
20113378.86M26,281$23.89M
201236612.06M32,956$32.65M
201336513.14M35,988$35.92M
201436513.09M35,862$37.86M
201536513.80M37,810$42.42M
20161435.98M41,835$18.84M

Finding: Before the fix, a year-grain demand chart made 2016 look like a collapse. With the updated daily line, demand clearly trends upward and 2016 remains strong on a per-day basis (~41.8K avg daily units vs ~37.8K in 2015). Annual KPI totals can still look low for 2016 when all years are selected — that is partial-year coverage (143 days), not a demand crash. Prefer average daily metrics or same-calendar-window YoY (Jan–22 May 2016 vs Jan–22 May 2015: sales +18.0%).

3.2 Growth is real on comparable years

On full years 2012→2015, sales CAGR is about 9.1%. Year-over-year sales: 2013 +10.0%, 2014 +5.4%, 2015 +12.0%. Units grew more slowly than sales in later years (price / mix effects). The dashboard YoY card (~27%) reflects a DAX SAMEPERIODLASTYEAR over the full selected range (including asymmetric year edges), not a clean full-year 2015 vs 2014 compare.

3.3 Store concentration — CA_3 dominates

Ten M5 stores across CA / TX / WI. Ranking by sales value matches the dashboard bar chart exactly:

RankStoreSalesShare of total
1CA_3$32.70M17.1%
2CA_1$22.95M12.0%
3TX_2$20.89M10.9%
10CA_4$12.47M6.5%

Finding: CA_3 sells ~2.6× CA_4. Top 3 stores ≈ 40% of sales. State mix: CA 44.9% · TX 28.8% · WI 26.4%. California is both the largest region and the home of the best and worst stores — store-level ops matter more than state label alone.

3.4 Category mix — FOODS is the business

FOODS $111.1M (58.0%), HOUSEHOLD $57.1M (29.8%), HOBBIES $23.3M (12.2%). FOODS share drifts down slightly across full years (≈60% in 2011–12 → ≈55% in 2015) as HOUSEHOLD/HOBBIES grow, but FOODS remains the primary revenue engine and the natural focus for demand-planning accuracy.

3.5 Calendar & seasonality

4. Dashboard quality notes

Optional polish: format the YTD card as Percentage with 1–2 decimals so it displays 18.0% instead of 0.18.

5. What a data-analysis project report should include

For this Walmart M5 platform project, a complete analysis write-up (course / portfolio / stakeholder pack) should cover the sections below — not only dashboard screenshots.

SectionWhat to deliverThis project status
1. Problem & objective Business question (demand visibility, store/category performance), success criteria FMCG demand platform on M5 — defined
2. Data understanding Sources, grain, time span, entities (item/store/day), known gaps Reports 01–02; partial 2011/2016 documented here
3. Pipeline / methodology Ingestion → Medallion → orchestration; reproducible transforms Reports 02–07 complete
4. Data quality Row counts, nulls, price coverage, referential integrity, outliers (Christmas) Gold 79.2% priced facts; calendar zeros noted
5. Exploratory analysis (EDA) Trends, seasonality, concentration, category mix — with numbers This page (Executive) + gold_export script
6. Visualization & interaction Layout hierarchy, chart choices, slicers, cross-filter, sync, click-paths Section 2 of this report
7. BI / dashboard design Model relationships, DAX definitions, page layout, limitations powerbi/documentation/
8. Findings & recommendations Actionable insights (store focus, FOODS priority, YoY caveats) Section 2 above
9. Limitations & next work No causal promo model yet; forecast horizon; more DQ tests Pages 2–4 Store/Product/Demand still to analyse formally
10. Appendix Table schemas, DAX list, job IDs, how to refresh Existing docs + Gold export path

6. Recommendations (from Executive view)

  1. Optional polish: format 2016 YTD vs 2015 YTD as Percentage (18.0%) instead of 0.18.
  2. Caption the demand chart if needed: “2016 series ends 22 May (partial year)”.
  3. Treat CA_3 as the benchmark store and CA_4 as a turnaround / assortment study case.
  4. Weight demand-planning effort toward FOODS (58% sales) while monitoring HOUSEHOLD growth share.
  5. Always exclude or specially model 25 Dec in forecasting baselines.
  6. Re-run python scripts/analyze_executive_dashboard.py after each Gold refresh to confirm the dashboard still matches export.

7. Reproduce

python scripts/analyze_executive_dashboard.py

Inputs: data/gold_export/agg_*.parquet, dim_date.parquet. Dashboard screenshot: assets/executive-dashboard-page1.png (Figure 1 above). Power BI page Executive with years 2011–2016 selected.