# Vizro is an open-source toolkit for creating modular data visualization applications.
# check out https://github.com/mckinsey/vizro for more info about Vizro
# and checkout https://vizro.readthedocs.io/en/stable/ for documentation.
import vizro.plotly.express as px
import vizro.models as vm
from vizro.models.types import capture
import plotly.graph_objects as go
import numpy as np
import pandas as pd
from vizro.managers import data_manager
data_manager["gapminder"] = px.data.gapminder()
data_manager["stocks"] = px.data.stocks()
####### Function definitions ######
@capture("graph")
def revenue_trend(data_frame):
"""
Creates a professional line chart with area fill showing revenue trend over time.
The chart displays the average of all stock values as total revenue.
"""
# Create a copy to avoid modifying original data
df = data_frame.copy()
# Convert date column to datetime
df["date"] = pd.to_datetime(df["date"])
# Convert stock columns to numeric (they are currently strings)
stock_columns = ["GOOG", "AAPL", "AMZN", "FB", "NFLX", "MSFT"]
for col in stock_columns:
df[col] = pd.to_numeric(df[col], errors="coerce")
# Calculate average of all stock values as total revenue
df["total_revenue"] = df[stock_columns].mean(axis=1)
# Sort by date
df = df.sort_values("date")
# Create figure
fig = go.Figure()
# Add area fill
fig.add_trace(
go.Scatter(
x=df["date"],
y=df["total_revenue"],
mode="lines+markers",
name="Total Revenue",
line=dict(
color="#1f77b4", width=3, shape="spline", smoothing=1.3 # Smooth line
),
marker=dict(
size=8,
color="#1f77b4",
symbol="circle",
line=dict(color="white", width=2),
),
fill="tozeroy",
fillcolor="rgba(31, 119, 180, 0.2)",
hovertemplate="<b>Date</b>: %{x|%Y-%m-%d}<br><b>Revenue</b>: %{y:.4f}<extra></extra>",
)
)
# Update layout with professional styling for executive dashboard
fig.update_layout(
title={
"text": "<b>Revenue Trend Analysis</b>",
"x": 0.5,
"xanchor": "center",
"font": {"size": 24, "color": "#2c3e50", "family": "Arial Black"},
},
xaxis=dict(
title="<b>Date</b>",
titlefont=dict(size=14, color="#2c3e50", family="Arial"),
showgrid=True,
gridcolor="rgba(220, 220, 220, 0.5)",
showline=True,
linewidth=2,
linecolor="#2c3e50",
mirror=True,
tickfont=dict(size=11, color="#2c3e50"),
),
yaxis=dict(
title="<b>Average Stock Value (Total Revenue)</b>",
titlefont=dict(size=14, color="#2c3e50", family="Arial"),
showgrid=True,
gridcolor="rgba(220, 220, 220, 0.5)",
showline=True,
linewidth=2,
linecolor="#2c3e50",
mirror=True,
tickfont=dict(size=11, color="#2c3e50"),
tickformat=".4f",
),
plot_bgcolor="white",
paper_bgcolor="#f8f9fa",
hovermode="x unified",
hoverlabel=dict(bgcolor="white", font_size=12, font_family="Arial"),
showlegend=True,
legend=dict(
orientation="h",
yanchor="bottom",
y=1.02,
xanchor="right",
x=1,
font=dict(size=12, color="#2c3e50"),
),
margin=dict(l=80, r=40, t=100, b=80),
height=500,
)
return fig
@capture("graph")
def monthly_variance(data_frame):
"""
Creates a waterfall chart showing monthly performance variance for stocks.
Displays monthly changes with bars indicating positive and negative variances from baseline.
"""
# Create a copy of the dataframe
df = data_frame.copy()
# Convert date column to datetime
df["date"] = pd.to_datetime(df["date"])
# Convert stock columns to float
stock_columns = ["GOOG", "AAPL", "AMZN", "FB", "NFLX", "MSFT"]
for col in stock_columns:
df[col] = pd.to_numeric(df[col], errors="coerce")
# Sort by date
df = df.sort_values("date").reset_index(drop=True)
# Calculate portfolio average performance
df["portfolio_avg"] = df[stock_columns].mean(axis=1)
# Calculate monthly variance (change from previous period)
df["variance"] = df["portfolio_avg"].diff()
df["variance_pct"] = df["variance"] * 100 # Convert to percentage points
# Prepare data for waterfall chart
dates = df["date"].dt.strftime("%Y-%m-%d").tolist()
# Create measure types: relative for changes, total for cumulative
measure = ["absolute"] + ["relative"] * (len(df) - 1)
# Values for waterfall
values = [df["portfolio_avg"].iloc[0]] + df["variance"].iloc[1:].tolist()
# Text labels showing percentage change
text_labels = ["Baseline: {:.2f}".format(df["portfolio_avg"].iloc[0])]
for i in range(1, len(df)):
var_pct = df["variance_pct"].iloc[i]
text_labels.append(
"{:+.2f}%".format(var_pct) if not pd.isna(var_pct) else "0.00%"
)
# Create waterfall chart
fig = go.Figure(
go.Waterfall(
name="Portfolio Performance",
orientation="v",
measure=measure,
x=dates,
y=values,
text=text_labels,
textposition="outside",
connector={"line": {"color": "rgb(63, 63, 63)", "width": 2}},
increasing={"marker": {"color": "green"}},
decreasing={"marker": {"color": "red"}},
totals={"marker": {"color": "blue"}},
)
)
# Update layout for executive presentation
fig.update_layout(
title={
"text": "Monthly Portfolio Performance Variance<br><sub>Average Performance Across All Stocks</sub>",
"x": 0.5,
"xanchor": "center",
"font": {"size": 20, "color": "#2c3e50"},
},
xaxis={
"title": "Date",
"tickangle": -45,
"showgrid": True,
"gridcolor": "#e0e0e0",
},
yaxis={
"title": "Normalized Performance Index",
"showgrid": True,
"gridcolor": "#e0e0e0",
"zeroline": True,
"zerolinecolor": "#000000",
"zerolinewidth": 2,
},
plot_bgcolor="white",
paper_bgcolor="white",
font={"family": "Arial, sans-serif", "size": 12},
showlegend=False,
height=600,
margin={"t": 100, "b": 100, "l": 80, "r": 80},
)
return fig
@capture("graph")
def revenue_by_segment(data_frame):
"""
Creates a horizontal bar chart showing total values by stock ticker (business segment).
Bars are sorted by value in descending order with a professional color scheme.
"""
# Get stock columns (exclude date column)
stock_columns = [col for col in data_frame.columns if col != "date"]
# Convert stock columns to numeric (they are stored as strings)
totals = []
for col in stock_columns:
# Convert to numeric and sum
total = pd.to_numeric(data_frame[col], errors="coerce").sum()
totals.append(total)
# Create DataFrame for plotting
chart_data = pd.DataFrame({"Segment": stock_columns, "Total_Value": totals})
# Sort by total value descending
chart_data = chart_data.sort_values(
"Total_Value", ascending=True
) # ascending=True for horizontal bars (bottom to top)
# Professional color scheme - blues and grays suitable for executive presentations
colors = ["#1f77b4", "#4292c6", "#6baed6", "#9ecae1", "#c6dbef", "#deebf7"]
# Create horizontal bar chart
fig = go.Figure()
fig.add_trace(
go.Bar(
y=chart_data["Segment"],
x=chart_data["Total_Value"],
orientation="h",
marker=dict(
color=colors[: len(chart_data)],
line=dict(color="rgba(255, 255, 255, 0.5)", width=1),
),
text=chart_data["Total_Value"].round(2),
textposition="auto",
textfont=dict(size=11, color="white", family="Arial"),
)
)
# Update layout for professional appearance
fig.update_layout(
title=dict(
text="Revenue by Business Segment",
font=dict(size=20, family="Arial", color="#2c3e50"),
x=0.5,
xanchor="center",
),
xaxis=dict(
title="Total Value",
titlefont=dict(size=14, family="Arial", color="#2c3e50"),
showgrid=True,
gridcolor="rgba(200, 200, 200, 0.3)",
zeroline=True,
),
yaxis=dict(
title="Stock Ticker",
titlefont=dict(size=14, family="Arial", color="#2c3e50"),
showgrid=False,
),
plot_bgcolor="white",
paper_bgcolor="white",
font=dict(family="Arial", size=12, color="#2c3e50"),
height=500,
margin=dict(l=100, r=50, t=80, b=60),
showlegend=False,
)
return fig
@capture("graph")
def performance_gauge(data_frame):
"""
Creates a gauge chart showing year-to-date performance vs target.
Calculates the average growth rate across all stocks and displays it as a percentage.
"""
# Create a copy to avoid modifying original data
df = data_frame.copy()
# Convert date column to datetime
df["date"] = pd.to_datetime(df["date"])
# Convert stock columns to numeric
stock_columns = ["GOOG", "AAPL", "AMZN", "FB", "NFLX", "MSFT"]
for col in stock_columns:
df[col] = pd.to_numeric(df[col], errors="coerce")
# Sort by date
df = df.sort_values("date")
# Calculate growth rate for each stock (latest value / earliest value - 1)
growth_rates = []
for col in stock_columns:
earliest_value = df[col].iloc[0]
latest_value = df[col].iloc[-1]
if (
earliest_value != 0
and not pd.isna(earliest_value)
and not pd.isna(latest_value)
):
growth_rate = ((latest_value / earliest_value) - 1) * 100
growth_rates.append(growth_rate)
# Calculate average growth rate
avg_growth_rate = np.mean(growth_rates) if growth_rates else 0
# Define target (assuming 10% growth target)
target = 10
# Create gauge chart
fig = go.Figure(
go.Indicator(
mode="gauge+number+delta",
value=avg_growth_rate,
domain={"x": [0, 1], "y": [0, 1]},
# title={"text": "Year-to-Date Performance vs Target", "font": {"size": 24}},
delta={"reference": target, "suffix": "%", "valueformat": ".2f"},
number={"suffix": "%", "valueformat": ".2f"},
gauge={
"axis": {"range": [None, 50], "ticksuffix": "%"},
"bar": {"color": "darkblue"},
"steps": [
{
"range": [0, 5],
"color": "rgba(255, 0, 0, 0.3)",
}, # Red zone: Below target
{
"range": [5, 15],
"color": "rgba(255, 255, 0, 0.3)",
}, # Yellow zone: On target
{
"range": [15, 50],
"color": "rgba(0, 255, 0, 0.3)",
}, # Green zone: Above target
],
"threshold": {
"line": {"color": "red", "width": 4},
"thickness": 0.75,
"value": target,
},
},
)
)
fig.update_layout(
height=400, margin=dict(l=20, r=20, t=80, b=20), font={"size": 14}
)
return fig
####### Data Manager Settings #####
#######!!! UNCOMMENT BELOW !!!#####
########### Model code ############
model = vm.Dashboard(
id="executive-dashboard",
pages=[
vm.Page(
id="financial-overview",
components=[
vm.Card(
id="revenue-kpi",
type="card",
text="### Total Revenue\n# $2.4B\n**↑ 12.5%** vs prior year",
),
vm.Card(
id="profit-kpi",
type="card",
text="### Operating Margin\n# 23.8%\n**↑ 1.2pp** vs prior year",
),
vm.Card(
id="efficiency-kpi",
type="card",
text="### EBITDA\n# $567M\n**↑ 15.3%** vs prior year",
),
vm.Graph(
id="revenue-trend-chart",
type="graph",
figure=revenue_trend(data_frame="stocks"),
),
vm.Graph(
id="segment-performance",
type="graph",
figure=revenue_by_segment(
data_frame="stocks"
),
),
vm.Graph(
id="monthly-variance-chart",
type="graph",
figure=monthly_variance(
data_frame="stocks"
),
),
],
title="Financial Overview",
layout=vm.Grid(
id="20fa3325", type="grid", grid=[[0], [1], [2], [3], [4], [5]]
),
),
vm.Page(
id="operations-overview",
components=[
vm.Card(
id="capacity-kpi",
type="card",
text="### Capacity Utilization\n# 87.4%\n**↑ 3.2%** vs target",
),
vm.Card(
id="efficiency-ops-kpi",
type="card",
text="### Operational Efficiency\n# 94.2%\n**On Target** (>90%)",
),
vm.Card(
id="incidents-kpi",
type="card",
text="### Safety Score\n# 98.1%\n**↑ 0.4%** vs prior period",
),
vm.Graph(
id="performance-gauge-chart",
type="graph",
figure=performance_gauge(
data_frame="stocks"
),
),
vm.Graph(
id="regional-performance",
type="graph",
figure=px.bar(
data_frame="gapminder",
x="continent",
y="gdpPercap",
color="continent",
title="Regional Performance (GDP per Capita)",
),
),
],
title="Operations & Performance",
layout=vm.Grid(id="664cab67", type="grid", grid=[[0], [1], [2], [3], [4]]),
),
vm.Page(
id="strategic-initiatives",
components=[
vm.Card(
id="initiatives-status",
type="card",
text="## Strategic Initiatives Status\n\n### On Track: 12 projects\n### At Risk: 3 projects \n### Delayed: 1 project\n\n**Overall Portfolio Health:** 75% Green",
),
vm.Card(
id="key-risks",
type="card",
text="## Key Risks & Mitigations\n\n**Supply Chain**: Medium Risk - Diversification underway\n\n**Talent Retention**: Low Risk - Programs implemented\n\n**Market Volatility**: Medium Risk - Monitoring closely",
),
vm.Graph(
id="initiative-timeline",
type="graph",
figure=px.scatter(
data_frame="gapminder",
x="year",
y="lifeExp",
color="continent",
size="pop",
title="Strategic Initiative Progress Timeline",
),
),
],
title="Strategic Initiatives",
layout=vm.Grid(id="75dbe666", type="grid", grid=[[0], [1], [2]]),
),
],
title="Executive Dashboard - FY2024",
)
from vizro import Vizro
Vizro().build(model).run()