Executive summary
- Purpose: one-page KPI that shows latest median rent, YoY%, and where pressure is highest.
- Outcome: an embedded report (below) with filters by beds & area; top/bottom areas surface immediately.
- Impact: reduces monthly preparation time for PR/policy updates; gives a single source of truth for rent trends.
Interactive report
Try selecting beds/area on the left. Cards show the latest month; the bar ranks areas by “pressure score”.
Introduction
What problem are we solving?
Local councils and housing NGOs need a simple, credible view of rental stress to inform public updates and resource allocation. Raw bond data and ad-hoc spreadsheets make month-on-month changes hard to trust and even harder to communicate.
Problems
Key pain points
- Fragmented metrics: median rents and year-over-year deltas are calculated differently by each team.
- No “where to look” signal: leaders can’t see which areas are heating up without deep analysis.
- Slow monthly cycle: preparing slides from CSVs takes hours, risking stale numbers.
Success looked like: one page, latest month KPIs, obvious top/bottom areas, and a link that anyone can open.
Solutions
Chosen approach
- Data model: monthly grain in Postgres (
month, area_code, beds, rent_median, pressure_score). - Standardised measures (DAX): “Median Rent (latest)” and “YoY % (latest)” so every visual agrees.
- Design: two slicers (beds, area), monthly line for trend, Top pressure score bar chart (slicer-immune), KPI cards for the latest month.
- Distribution: Power BI “Publish to web” for frictionless viewing; the same iFrame is used on the portfolio site.
Why this works
- Speed: monthly update becomes a dataset refresh, not a slide rebuild.
- Clarity: executives get a 10-second answer: “What changed, and where should we look?”
Alternatives considered
- Static PDF dashboards — simpler to share but no filters or drill; discarded.
- Tableau Public — similar reach, but the team already operates Power BI; kept BI stack consistent.
- Private embed — more control, but adds login friction for public comms; “Publish to web” fit the brief.
Key measures (DAX)
// Latest month label
Latest month label :=
FORMAT(MAX('Rent_Affordability'[month]), "yyyy MMM")
// Median Rent (latest)
Median Rent (latest) :=
VAR _latest = CALCULATE(MAX('Rent_Affordability'[month]), ALL('Rent_Affordability'))
RETURN CALCULATE(AVERAGE('Rent_Affordability'[rent_median]),
'Rent_Affordability'[month] = _latest)
// YoY % (latest)
YoY % (latest) :=
VAR _latest = CALCULATE(MAX('Rent_Affordability'[month]), ALL('Rent_Affordability'))
VAR _cur = CALCULATE(AVERAGE('Rent_Affordability'[rent_median]), 'Rent_Affordability'[month] = _latest)
VAR _prev = CALCULATE(AVERAGE('Rent_Affordability'[rent_median]),
FILTER(ALL('Rent_Affordability'),
YEAR('Rent_Affordability'[month])=YEAR(_latest)-1 &&
MONTH('Rent_Affordability'[month])=MONTH(_latest)))
RETURN DIVIDE(_cur - _prev, _prev)
Conclusion
What we learned
- A single, standardised set of measures removes debate and speeds decisions.
- Leaders engage more with a one-page KPI + “where to look” ranking than with multi-tab reports.
- For public comms, zero-friction access (iFrame) beats feature-rich but gated dashboards.
Example (snapshot when published): latest median rent $475, YoY 1.06%, pressure highest in Wellington among compared areas.
Next steps
Recommendations
- Granularity: add sub-areas to highlight pockets of stress within a city.
- Distribution: switch to secure embed for internal stakeholders; keep public iFrame for outreach.
- Automation: schedule dataset refresh post-ingestion so the site always reflects the latest month.