Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Demo] Replace KPI cards with dynamic figure functions #648

Merged
merged 32 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
332a01f
Filter on two years only
huong-li-nguyen Aug 22, 2024
2edcbc5
Quickly scratch out data wrangling
huong-li-nguyen Aug 23, 2024
40dd1b9
Tidy
huong-li-nguyen Aug 23, 2024
f3548c4
Replace with dynamic KPI cards
huong-li-nguyen Aug 23, 2024
2f1631b
Merge branch 'main' into tidy/replace-kpi-cards
huong-li-nguyen Aug 23, 2024
614b8c5
Make clear that 2020 is shown
huong-li-nguyen Aug 23, 2024
fdd3fd2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 23, 2024
1bb3519
Fix formatting
huong-li-nguyen Aug 23, 2024
457f974
Tidy
huong-li-nguyen Aug 23, 2024
9136f9c
Replace with FlexBox
huong-li-nguyen Aug 23, 2024
b8a4b83
Tidy
huong-li-nguyen Aug 23, 2024
b4d616c
Merge branch 'tidy/replace-kpi-cards' of https://github.com/mckinsey/…
huong-li-nguyen Aug 23, 2024
bfce1fb
Fix flex-container
huong-li-nguyen Aug 26, 2024
e1a45d2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 26, 2024
144fbb5
Fix scroll
huong-li-nguyen Aug 26, 2024
4c4178c
Fix coloring in pie chart
huong-li-nguyen Aug 26, 2024
37eff27
Fix sizing
huong-li-nguyen Aug 26, 2024
3ec6337
Lint
huong-li-nguyen Aug 26, 2024
5ecad4f
Simplify second page view
huong-li-nguyen Aug 26, 2024
f9939ea
Merge branch 'tidy/replace-kpi-cards' of https://github.com/mckinsey/…
huong-li-nguyen Aug 26, 2024
49c976a
Lint
huong-li-nguyen Aug 26, 2024
b1eb2ff
Fix area chart
huong-li-nguyen Aug 26, 2024
bbec838
Change to 2018/2019
huong-li-nguyen Aug 26, 2024
4e6016c
Apply reverse color coding for one KPI
huong-li-nguyen Aug 26, 2024
5a1c442
Update README.md
huong-li-nguyen Aug 26, 2024
113ed09
Update README and lint
huong-li-nguyen Aug 26, 2024
73d171c
Remove redundant comments
huong-li-nguyen Aug 26, 2024
e7f91cf
Replace gif
huong-li-nguyen Aug 26, 2024
fb604a5
Add docstrings
huong-li-nguyen Aug 26, 2024
5dfd39c
Tidy README
huong-li-nguyen Aug 26, 2024
ef4fdbd
Reduce gif size
huong-li-nguyen Aug 26, 2024
5dc0861
Add icons and tidy
huong-li-nguyen Aug 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!--
A new scriv changelog fragment.

Uncomment the section that is right (remove the HTML comment wrapper).
-->

<!--
### Highlights ✨

- A bullet item for the Highlights ✨ category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))

-->
<!--
### Removed

- A bullet item for the Removed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))

-->
<!--
### Added

- A bullet item for the Added category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))

-->
<!--
### Changed

- A bullet item for the Changed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))

-->
<!--
### Deprecated

- A bullet item for the Deprecated category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))

-->
<!--
### Fixed

- A bullet item for the Fixed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))

-->
<!--
### Security

- A bullet item for the Security category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))

-->
52 changes: 31 additions & 21 deletions vizro-core/examples/kpi/README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,40 @@
# KPI dashboard
# KPI Dashboard

This dashboard provides an example of a Key Performance Indicator (KPI) dashboard, designed to help users get started and extend further.
It uses fictional budget data to demonstrate the capabilities of Vizro using real world applications.
This dashboard provides an example of a Key Performance Indicator (KPI) dashboard, designed to help users get started
and extend further. It uses fictional budget data to demonstrate the capabilities of Vizro using real world applications.

Special thanks to the [#RWFD Real World Fake Data initiative](https://opendatainitiative.io/), a community project that
**Created by:** [Huong Li Nguyen](https://github.com/huong-li-nguyen)

---

### 🗓️ Data

Special thanks to the [#RWFD Real World Fake Data initiative](https://data.world/markbradbourne/rwfd-real-world-fake-data), a community project that
provides high-quality fake data for creating realistic dashboard examples for real-world applications.

Note: The data has been additionally edited for the purpose of this example.
**Note:** The data has been additionally edited for the purpose of this example.

### 📊 Plotly resources

- [Bar charts](https://plotly.com/python/bar-charts/)
- [Pie charts](https://plotly.com/python/pie-charts/)
- [Choropleth maps](https://plotly.com/python/choropleth-maps/)
- [Unstacked area charts](https://plotly.com/python/filled-area-plots/)

<img src="./assets/images/kpi_dashboard.gif" alt="Gif to KPI dashboard">
### 🚀 Vizro features applied

- [Vizro tutorial on pages, layouts and dashboards](https://vizro.readthedocs.io/en/stable/pages/tutorials/explore-components/)
- [Custom components](https://vizro.readthedocs.io/en/stable/pages/user-guides/custom-components/)
- [Custom charts](https://vizro.readthedocs.io/en/stable/pages/user-guides/custom-charts/)
- [Custom CSS](https://vizro.readthedocs.io/en/stable/pages/user-guides/assets/)

### 🖥️ App demo

<img src="./images/kpi-dashboard.gif" alt="Gif to KPI dashboard" width="600">

---

## How to run the example locally

1. If you have `hatch` set up, run the example with the command `hatch run example kpi`. Otherwise, run the `app.py` file with your environment activated where `vizro` is installed.
1. Run the `app.py` file with your environment activated where `vizro` is installed.
2. You should now be able to access the app locally via http://127.0.0.1:8050/.

## Possible future iterations

- Enable selection of year filter
- Enable current year vs. past year comparison
- Enable dynamic KPI Cards
- Bar - Enable drill-downs from Issue to Sub-issue and Product to Sub-product
- Bar - Reformat numbers with commas in bar chart
- Bar - Left-align y-axis labels
- Bar - Shorten labels
- Line - Customize function to always show selected year vs. past year
- Table-view - Check why date format does not work on `Date Received`
- Table-view - Add icons to `On time?` column
- Table-view - Improve speed by applying cache or overcome limitation that entire data set is loaded in
159 changes: 81 additions & 78 deletions vizro-core/examples/kpi/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,113 +2,128 @@

import pandas as pd
import vizro.models as vm
from utils._charts import COLUMN_DEFS, KPI, bar, choropleth, line, pie
from utils._helper import clean_data_and_add_columns
from utils._charts import COLUMN_DEFS, FlexContainer, area, bar, choropleth, pie
from utils._helper import clean_data_and_add_columns, create_data_for_kpi_cards
from vizro import Vizro
from vizro.actions import filter_interaction
from vizro.figures import kpi_card_reference
from vizro.tables import dash_ag_grid

# DATA --------------------------------------------------------------------------------------------
df_complaints = pd.read_csv("https://query.data.world/s/glbdstahsuw3hjgunz3zssggk7dsfu?dws=00000")
df_complaints = clean_data_and_add_columns(df_complaints)
vm.Container.add_type("components", KPI)
df_kpi_cards = create_data_for_kpi_cards(df_complaints)
vm.Page.add_type("components", FlexContainer)


# SUB-SECTIONS ------------------------------------------------------------------------------------
kpi_banner = vm.Container(
id="kpi-banner",
title="",
kpi_banner = FlexContainer(
components=[
# Note: For some KPIs the icon/sign go in opposite directions as an increase e.g. in complaints is negative
KPI(
title="Total Complaints",
value="75.513",
icon="arrow_circle_up",
sign="delta-neg",
ref_value="6.8% vs. LY",
),
KPI(
title="Closed Complaints",
value="99.6%",
icon="arrow_circle_up",
sign="delta-pos",
ref_value="+0.2% vs. LY",
vm.Figure(
id="kpi-reverse-coloring",
figure=kpi_card_reference(
df_kpi_cards,
value_column="Total Complaints_2019",
reference_column="Total Complaints_2018",
title="Total Complaints",
value_format="{value:.0f}",
reference_format="{delta_relative:+.1%} vs. 2018 ({reference:.0f})",
icon="person",
),
),
KPI(
title="Open Complaints",
value="0.4%",
icon="arrow_circle_down",
sign="delta-pos",
ref_value="-0.2% vs. LY",
vm.Figure(
figure=kpi_card_reference(
df_kpi_cards,
value_column="Closed Complaints_2019",
reference_column="Closed Complaints_2018",
title="Closed Complaints",
value_format="{value:.1f}%",
reference_format="{delta:+.1f}pp vs. 2018 ({reference:.1f}%)",
icon="inventory",
)
),
KPI(
title="Timely Response",
value="98.1%",
icon="arrow_circle_up",
sign="delta-pos",
ref_value="+10.5% vs. LY",
vm.Figure(
figure=kpi_card_reference(
df_kpi_cards,
value_column="Timely response_2019",
reference_column="Timely response_2018",
title="Timely Response",
value_format="{value:.1f}%",
reference_format="{delta:+.1f}pp vs. 2018 ({reference:.1f}%)",
icon="timer",
)
),
KPI(
title="Closed w/o cost",
value="84.5%",
icon="arrow_circle_down",
sign="delta-neg",
ref_value="-8.5% vs. LY",
vm.Figure(
figure=kpi_card_reference(
df_kpi_cards,
value_column="Closed w/o cost_2019",
reference_column="Closed w/o cost_2018",
title="Closed w/o cost",
value_format="{value:.1f}%",
reference_format="{delta:.1f}pp vs. 2018 ({reference:.1f}%)",
icon="payments",
)
),
KPI(
title="Consumer disputed",
value="9.5%",
icon="arrow_circle_up",
sign="delta-neg",
ref_value="+2.3% vs. LY",
vm.Figure(
figure=kpi_card_reference(
df_kpi_cards,
value_column="Consumer disputed_2019",
reference_column="Consumer disputed_2018",
title="Consumer disputed",
value_format="{value:.1f}%",
reference_format="{delta:+.1f}pp vs. 2018 ({reference:.1f}%)",
icon="sentiment_dissatisfied",
)
huong-li-nguyen marked this conversation as resolved.
Show resolved Hide resolved
),
],
classname="kpi-banner",
)

bar_charts_tabbed = vm.Tabs(
tabs=[
vm.Container(
title="By Issue",
title="By Product",
components=[
vm.Graph(
figure=bar(
data_frame=df_complaints,
y="Issue",
y="Product",
x="Complaint ID",
),
)
],
),
vm.Container(
title="By Product",
title="By Channel",
components=[
vm.Graph(
figure=bar(
data_frame=df_complaints,
y="Product",
y="Channel",
x="Complaint ID",
),
)
],
),
vm.Container(
title="By Channel",
title="By Region",
components=[
vm.Graph(
figure=bar(
data_frame=df_complaints,
y="Channel",
y="Region",
x="Complaint ID",
),
)
],
),
vm.Container(
title="By Region",
title="By Issue",
components=[
vm.Graph(
figure=bar(
data_frame=df_complaints,
y="Region",
y="Issue",
x="Complaint ID",
),
)
Expand All @@ -123,26 +138,22 @@
layout=vm.Layout(
grid=[
[0, 0],
[0, 0],
[1, 2],
[1, 2],
[1, 2],
[1, 3],
[1, 3],
[1, 3],
],
),
components=[
kpi_banner,
bar_charts_tabbed,
vm.Graph(figure=line(data_frame=df_complaints, y="Complaint ID", x="Year-Month Received")),
vm.Graph(figure=area(data_frame=df_complaints, y="Complaint ID", x="Month")),
vm.Graph(
figure=pie(
data_frame=df_complaints[df_complaints["Company response - Closed"] != "Not closed"],
custom_order=[
"Closed with explanation",
"Closed without relief",
"Closed with non-monetary relief",
"Closed with relief",
"Closed with monetary relief",
],
values="Complaint ID",
names="Company response - Closed",
title="Closed company responses",
Expand All @@ -153,23 +164,15 @@

page_region = vm.Page(
title="Regional View",
layout=vm.Layout(grid=[[0, 0]] + [[1, 2]] * 4),
layout=vm.Layout(grid=[[0, 1]]),
components=[
vm.Card(
text="""
##### Click on a state inside the map to filter the bar charts on the right.

- Which state has the most complaints?
- What are the three biggest issues in California?
- What is the product with the most complaints in Texas?
"""
),
vm.Graph(
figure=choropleth(
data_frame=df_complaints,
locations="State",
color="Complaint ID",
title="Complaints by State",
title="Complaints by State <br><sup> ⤵ Click on a state to filter the "
"charts on the right. Refresh the page to deselect.</sup>",
custom_data=["State"],
),
actions=[
Expand All @@ -181,26 +184,26 @@
vm.Tabs(
tabs=[
vm.Container(
title="By Issue",
title="By Product",
components=[
vm.Graph(
id="regional-issue",
id="regional-product",
figure=bar(
data_frame=df_complaints,
y="Issue",
y="Product",
x="Complaint ID",
),
)
],
),
vm.Container(
title="By Product",
title="By Issue",
components=[
vm.Graph(
id="regional-product",
id="regional-issue",
figure=bar(
data_frame=df_complaints,
y="Product",
y="Issue",
x="Complaint ID",
),
)
Expand Down Expand Up @@ -232,7 +235,7 @@

dashboard = vm.Dashboard(
pages=[page_exec, page_region, page_table],
title="Cumulus Financial Corporation",
title="Cumulus Financial Corp. - Fiscal Year 2019",
navigation=vm.Navigation(
nav_selector=vm.NavBar(
items=[
Expand Down
Loading
Loading