2023-06-02 12:15:46 +02:00
|
|
|
import math
|
|
|
|
from dash import Dash, dcc, html, Input, Output
|
|
|
|
import plotly.express as px
|
|
|
|
import plotly.graph_objects as go
|
|
|
|
import numpy as np
|
|
|
|
import pandas as pd
|
|
|
|
import dash_bootstrap_components as dbc
|
|
|
|
from sklearn.datasets import make_blobs
|
|
|
|
|
|
|
|
# new: more than one plot in a callback
|
|
|
|
# new: one plot as an input for another plot
|
|
|
|
# new: plotly go object
|
|
|
|
|
|
|
|
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
|
|
|
|
|
|
|
|
df = pd.DataFrame(
|
|
|
|
{
|
|
|
|
"y": np.random.normal(loc=0, scale=10, size=1000),
|
|
|
|
"x": np.random.normal(loc=10, scale=2, size=1000),
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
# define cluster colors
|
2023-06-03 13:13:03 +02:00
|
|
|
# https://loading.io/color/feature/Spectral-10/
|
|
|
|
COLORS = {
|
|
|
|
"0": "#9e0142",
|
|
|
|
"1": "#d53e4f",
|
|
|
|
"2": "#f46d43",
|
|
|
|
"3": "#fdae61",
|
|
|
|
"4": "#fee08b",
|
|
|
|
"5": "#e6f598",
|
|
|
|
"6": "#abdda4",
|
|
|
|
"7": "#66c2a5",
|
|
|
|
"8": "#3288bd",
|
|
|
|
"9": "#5e4fa2",
|
|
|
|
}
|
|
|
|
|
|
|
|
X, y = make_blobs(n_samples=300, centers=3, n_features=2, random_state=0)
|
2023-06-02 12:15:46 +02:00
|
|
|
|
|
|
|
cluster_df = pd.DataFrame(data=X, columns=["X", "Y"])
|
|
|
|
cluster_df["cluster"] = [str(i) for i in y]
|
|
|
|
|
|
|
|
app.layout = html.Div(
|
|
|
|
[
|
|
|
|
html.Div([html.H1("Dashboard 4")], className="header"),
|
|
|
|
html.Div(
|
|
|
|
[
|
|
|
|
dcc.Tabs(
|
|
|
|
id="tabs",
|
|
|
|
children=[
|
|
|
|
dcc.Tab(
|
|
|
|
label="Tab One",
|
|
|
|
id="tab_1_graphs",
|
|
|
|
children=[
|
|
|
|
html.Div(
|
|
|
|
[
|
|
|
|
dbc.Row(
|
|
|
|
[
|
|
|
|
dbc.Col(
|
|
|
|
[
|
|
|
|
dcc.Dropdown(
|
|
|
|
options=[
|
|
|
|
"red",
|
|
|
|
"green",
|
|
|
|
"blue",
|
|
|
|
],
|
|
|
|
value="red",
|
|
|
|
id="color",
|
|
|
|
multi=False,
|
|
|
|
)
|
|
|
|
],
|
|
|
|
width=6,
|
|
|
|
),
|
|
|
|
dbc.Col(
|
|
|
|
[
|
|
|
|
dcc.Slider(
|
|
|
|
min=math.floor(
|
|
|
|
df["y"].min()
|
|
|
|
),
|
|
|
|
max=math.ceil(
|
|
|
|
df["y"].max()
|
|
|
|
),
|
|
|
|
id="min_value",
|
|
|
|
)
|
|
|
|
],
|
|
|
|
width=6,
|
|
|
|
),
|
|
|
|
]
|
|
|
|
),
|
|
|
|
dbc.Row(
|
|
|
|
[
|
|
|
|
dbc.Col(
|
|
|
|
[dcc.Graph(id="graph_1")], width=6
|
|
|
|
),
|
|
|
|
dbc.Col(
|
|
|
|
[dcc.Graph(id="graph_2")], width=6
|
|
|
|
),
|
|
|
|
]
|
|
|
|
),
|
2023-06-03 13:35:48 +02:00
|
|
|
dbc.Row(
|
|
|
|
[
|
|
|
|
dbc.Col(width=6),
|
|
|
|
dbc.Col(
|
|
|
|
[dcc.Graph(id="graph_69")], width=6
|
|
|
|
),
|
|
|
|
]
|
|
|
|
),
|
2023-06-02 12:15:46 +02:00
|
|
|
],
|
|
|
|
className="tab_content",
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
dcc.Tab(
|
|
|
|
label="Tab Two",
|
|
|
|
id="tab_2_graphs",
|
|
|
|
children=[
|
|
|
|
html.Div(
|
|
|
|
[
|
2023-06-03 13:13:03 +02:00
|
|
|
dbc.Row(
|
|
|
|
[
|
|
|
|
dbc.Col(
|
|
|
|
[
|
|
|
|
dcc.Slider(
|
|
|
|
1,
|
|
|
|
10,
|
|
|
|
1,
|
|
|
|
value=3,
|
|
|
|
id="slider_1",
|
|
|
|
)
|
|
|
|
]
|
|
|
|
),
|
|
|
|
]
|
|
|
|
),
|
2023-06-02 12:15:46 +02:00
|
|
|
dbc.Row(
|
|
|
|
[
|
|
|
|
dbc.Col(
|
|
|
|
[dcc.Graph(id="graph_3")], width=8
|
|
|
|
),
|
|
|
|
dbc.Col(
|
|
|
|
[dcc.Graph(id="graph_4")], width=4
|
|
|
|
),
|
|
|
|
]
|
2023-06-03 13:13:03 +02:00
|
|
|
),
|
2023-06-02 12:15:46 +02:00
|
|
|
],
|
|
|
|
className="tab_content",
|
|
|
|
)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
],
|
|
|
|
className="content",
|
|
|
|
),
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@app.callback(Output("graph_1", "figure"), Input("color", "value"))
|
|
|
|
def update_graph_1(dropdown_value_color):
|
|
|
|
fig = px.histogram(df, x="y", color_discrete_sequence=[dropdown_value_color])
|
|
|
|
fig.update_layout(template="plotly_white")
|
|
|
|
return fig
|
|
|
|
|
|
|
|
|
|
|
|
@app.callback(Output("graph_2", "figure"), Input("min_value", "value"))
|
|
|
|
def update_graph_2(min_value):
|
|
|
|
if min_value:
|
|
|
|
dff = df[df["y"] > min_value]
|
|
|
|
else:
|
|
|
|
dff = df
|
|
|
|
fig = px.scatter(dff, x="x", y="y")
|
2023-06-03 13:35:48 +02:00
|
|
|
fig.update_layout(template="plotly_white")
|
|
|
|
return fig
|
|
|
|
|
2023-06-03 13:36:23 +02:00
|
|
|
# 7a
|
2023-06-03 13:35:48 +02:00
|
|
|
@app.callback(Output("graph_69", "figure"), Input("graph_2", "relayoutData"))
|
|
|
|
def update_graph_2(selected_data):
|
|
|
|
if selected_data is None or (
|
|
|
|
isinstance(selected_data, dict) and "xaxis.range[0]" not in selected_data
|
|
|
|
):
|
|
|
|
dff = df
|
|
|
|
else:
|
|
|
|
dff = df[
|
|
|
|
(df["x"] >= selected_data.get("xaxis.range[0]"))
|
|
|
|
& (df["x"] <= selected_data.get("xaxis.range[1]"))
|
|
|
|
& (df["y"] >= selected_data.get("yaxis.range[0]"))
|
|
|
|
& (df["y"] <= selected_data.get("yaxis.range[1]"))
|
|
|
|
]
|
|
|
|
fig = px.scatter(dff, x="x", y="y")
|
2023-06-02 12:15:46 +02:00
|
|
|
fig.update_layout(template="plotly_white")
|
|
|
|
return fig
|
|
|
|
|
|
|
|
|
|
|
|
@app.callback(
|
|
|
|
Output("graph_3", "figure"),
|
|
|
|
Output("graph_4", "figure"),
|
|
|
|
Input("graph_3", "relayoutData"),
|
2023-06-03 13:13:03 +02:00
|
|
|
Input("slider_1", "value"),
|
2023-06-02 12:15:46 +02:00
|
|
|
)
|
2023-06-03 13:13:03 +02:00
|
|
|
def update_graph_3_and_4(selected_data, sliderValue):
|
2023-06-03 13:36:23 +02:00
|
|
|
## 7b
|
2023-06-03 13:13:03 +02:00
|
|
|
# forcing update of x, y and cluster_df with the proper am
|
|
|
|
X, y = make_blobs(
|
|
|
|
n_samples=100 * sliderValue, centers=sliderValue, n_features=2, random_state=0
|
|
|
|
)
|
|
|
|
cluster_df = pd.DataFrame(data=X, columns=["X", "Y"])
|
|
|
|
cluster_df["cluster"] = [str(i) for i in y]
|
|
|
|
|
2023-06-02 12:15:46 +02:00
|
|
|
if selected_data is None or (
|
|
|
|
isinstance(selected_data, dict) and "xaxis.range[0]" not in selected_data
|
|
|
|
):
|
|
|
|
cluster_dff = cluster_df
|
|
|
|
else:
|
|
|
|
cluster_dff = cluster_df[
|
|
|
|
(cluster_df["X"] >= selected_data.get("xaxis.range[0]"))
|
|
|
|
& (cluster_df["X"] <= selected_data.get("xaxis.range[1]"))
|
|
|
|
& (cluster_df["Y"] >= selected_data.get("yaxis.range[0]"))
|
|
|
|
& (cluster_df["Y"] <= selected_data.get("yaxis.range[1]"))
|
|
|
|
]
|
|
|
|
|
|
|
|
fig3 = px.scatter(
|
|
|
|
cluster_dff,
|
|
|
|
x="X",
|
|
|
|
y="Y",
|
|
|
|
color="cluster",
|
|
|
|
color_discrete_map=COLORS,
|
2023-06-03 13:13:03 +02:00
|
|
|
category_orders={"cluster": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]},
|
2023-06-02 12:15:46 +02:00
|
|
|
height=750,
|
|
|
|
)
|
|
|
|
fig3.update_layout(template="plotly_white", coloraxis_showscale=False)
|
|
|
|
fig3.update_traces(marker=dict(size=8))
|
|
|
|
|
|
|
|
group_counts = cluster_dff[["cluster", "X"]].groupby("cluster").count()
|
|
|
|
|
|
|
|
fig4 = go.Figure(
|
|
|
|
data=[
|
|
|
|
go.Bar(
|
|
|
|
x=group_counts.index,
|
|
|
|
y=group_counts["X"],
|
|
|
|
marker_color=[COLORS.get(i) for i in group_counts.index],
|
|
|
|
)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
fig4.update_layout(
|
|
|
|
height=750,
|
|
|
|
template="plotly_white",
|
|
|
|
title="<b>Counts per cluster</b>",
|
|
|
|
xaxis_title="cluster",
|
|
|
|
title_font_size=25,
|
|
|
|
)
|
|
|
|
return fig3, fig4
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
app.run_server(debug=True, port=8012)
|