Spaces:
Running
Running
"""Example to show dashboard configuration.""" | |
import pandas as pd | |
import vizro.models as vm | |
from vizro import Vizro | |
import vizro.plotly.express as px | |
from dash import get_asset_url, html | |
import dash_bootstrap_components as dbc | |
from vizro.models.types import capture | |
from vizro.tables import dash_ag_grid | |
from utils.helper import categorize_price, convert_price_to_numeric, columnDefs | |
from vizro.figures import kpi_card | |
# Custom charts are required because of the post-update calls | |
def bar(data_frame, top_n=20, **kwargs): | |
data_top = data_frame.head(top_n) | |
fig = px.bar(data_top, **kwargs) | |
fig.update_layout(title=f"Top {top_n} Games by {kwargs['x']}", yaxis_title="", yaxis_autorange="reversed") | |
return fig | |
def scatter(data_frame, top_n=20, **kwargs): | |
data_top = data_frame.head(top_n) | |
fig = px.scatter(data_top, **kwargs) | |
fig.update_layout( | |
title=f"Top {top_n} games by {kwargs['y']}. Each bubble represents a single game. The bigger the bubble, the more players." | |
) | |
return fig | |
def treemap(data_frame, top_n=20, **kwargs): | |
data_top = data_frame.head(top_n) | |
fig = px.treemap(data_top, **kwargs) | |
fig.update_traces(root_color="lightgrey") | |
fig.update_layout(title=f"Top {top_n} games by {kwargs['values']}. The bigger the square, the more players.") | |
return fig | |
# Tidy data set | |
players = pd.read_csv( | |
"https://raw.githubusercontent.com/plotly/Figure-Friday/refs/heads/main/2025/week-5/Steam%20Top%20100%20Played%20Games%20-%20List.csv" | |
) | |
players["Price Category"] = players["Price"].apply(categorize_price) | |
players["Price Numeric"] = players["Price"].apply(convert_price_to_numeric) | |
players["Current Players"] = pd.to_numeric(players["Current Players"].str.replace(",", "")) | |
players["Peak Today"] = pd.to_numeric(players["Peak Today"].str.replace(",", "")) | |
tabs = vm.Tabs( | |
tabs=[ | |
vm.Container( | |
title="Bar", | |
components=[ | |
vm.Graph( | |
id="bar", | |
figure=bar( | |
players, | |
y="Name", | |
x="Current Players", | |
title="Current Players by Game", | |
orientation="h", | |
color="Price Numeric", | |
), | |
) | |
], | |
), | |
vm.Container( | |
title="Treemap", | |
components=[ | |
vm.Graph( | |
id="treemap", | |
figure=treemap( | |
players, path=[px.Constant("All"), "Name"], values="Current Players", color="Price Numeric" | |
), | |
) | |
], | |
), | |
vm.Container( | |
title="Bubble", | |
components=[ | |
vm.Graph( | |
id="bubble", | |
figure=scatter( | |
players, | |
x="Price Numeric", | |
y="Current Players", | |
size="Current Players", | |
size_max=50, | |
opacity=0.5, | |
color="Price Numeric", | |
), | |
) | |
], | |
), | |
], | |
) | |
players_page = vm.Page( | |
title="Total Players 🎮", | |
layout=vm.Layout(grid=[[0, 1, 2, 3, 4]] + [[5, 5, 5, 5, 5]] * 5), | |
components=[ | |
vm.Figure( | |
id="kpi-1", | |
figure=kpi_card( | |
data_frame=players[players["Price Category"] == "Free To Play"], | |
value_column="Current Players", | |
value_format="{value:,}", | |
icon="groups", | |
title="Free to play", | |
), | |
), | |
vm.Figure( | |
id="kpi-2", | |
figure=kpi_card( | |
data_frame=players[players["Price Category"] == "Less than £15"], | |
value_column="Current Players", | |
value_format="{value:,}", | |
icon="group", | |
title="Less than £15", | |
), | |
), | |
vm.Figure( | |
id="kpi-3", | |
figure=kpi_card( | |
data_frame=players[players["Price Category"] == "£15-£30"], | |
value_column="Current Players", | |
value_format="{value:,}", | |
icon="person", | |
title="£15-£30", | |
), | |
), | |
vm.Figure( | |
id="kpi-4", | |
figure=kpi_card( | |
data_frame=players[players["Price Category"] == "£30-£45"], | |
value_column="Current Players", | |
value_format="{value:,}", | |
icon="people", | |
title="£30-£45", | |
), | |
), | |
vm.Figure( | |
id="kpi-5", | |
figure=kpi_card( | |
data_frame=players[players["Price Category"] == "More than 45£"], | |
value_column="Current Players", | |
value_format="{value:,}", | |
icon="groups", | |
title="More than 45£", | |
), | |
), | |
tabs, | |
], | |
controls=[ | |
vm.Parameter( | |
targets=[ | |
"bar.x", | |
"treemap.values", | |
"bubble.y", | |
"kpi-1.value_column", | |
"kpi-2.value_column", | |
"kpi-3.value_column", | |
"kpi-4.value_column", | |
"kpi-5.value_column", | |
], | |
selector=vm.RadioItems( | |
options=["Current Players", "Peak Today"], | |
title="Select metric in all charts", | |
), | |
), | |
vm.Parameter( | |
targets=["bar.top_n", "bubble.top_n", "treemap.top_n"], | |
selector=vm.Slider(min=10, max=50, step=5, value=20, title="Select top N:"), | |
), | |
vm.Filter( | |
column="Price Category", | |
selector=vm.Checklist( | |
options=["Free To Play", "Less than £15", "£15-£30", "£30-£45", "More than 45£"], | |
title="Select price category:", | |
), | |
), | |
vm.Filter(column="Name", selector=vm.Dropdown(title="Select game:")), | |
], | |
) | |
games_page = vm.Page( | |
title="Most played games 👾", | |
components=[ | |
vm.AgGrid( | |
figure=dash_ag_grid(players, columnDefs=columnDefs, dashGridOptions={"rowHeight": 56, "pagination": True}) | |
) | |
], | |
) | |
dashboard = vm.Dashboard( | |
title="Figure Friday - Week 5", | |
pages=[players_page, games_page], | |
navigation=vm.Navigation( | |
nav_selector=vm.NavBar( | |
items=[ | |
vm.NavLink(label="Players", pages=["Total Players 🎮"], icon="Person Play"), | |
vm.NavLink(label="Games", pages=["Most played games 👾"], icon="Stadia Controller"), | |
] | |
) | |
), | |
) | |
app = Vizro().build(dashboard) | |
app.dash.layout.children.append( | |
dbc.NavLink( | |
["Made with ", html.Img(src=get_asset_url("logo.svg"), id="banner", alt="Vizro logo"), "vizro"], | |
href="https://github.com/mckinsey/vizro", | |
target="_blank", | |
className="anchor-container", | |
) | |
) | |
server = app.dash.server | |
if __name__ == "__main__": | |
app.run() | |