Skip to content

Commit

Permalink
[Demo] Replace KPI cards with dynamic figure functions (#648)
Browse files Browse the repository at this point in the history
  • Loading branch information
huong-li-nguyen authored Aug 26, 2024
1 parent 369af7c commit 208af57
Show file tree
Hide file tree
Showing 9 changed files with 315 additions and 209 deletions.
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",
)
),
],
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

0 comments on commit 208af57

Please sign in to comment.