I have the written code below. I have two dropdown menus that work based on chained callbacks. the first dropdown menu gets the datasets and reads the columns’ names and updates the options in the second dropdown menu. Then, the parameters can be plotted on the chart. my dataframes look like this:
df={'col1':[12,15,25,33,26,33,39,17,28,25],
'col2':[35,33,37,36,36,26,31,21,15,29],
'col3':['A','A','A','A','B','B','B','B','B','B'],
'col4':[1,2,3,4,5,6,7,8,9,10]
I want to highlight the chart background depending on the categories in col3. I don’t understand why when I select the dataset from the first dropdown menu the background color for col3 appears on the chart (before selecting the parameters). I have used Prevent_initial_call = True, but the second callback still triggers.
import dash
from dash import Dash, html, dcc, Output, Input, State, MATCH, ALL
import plotly.express as px
import pandas as pd
import numpy as np
import dash_bootstrap_components as dbc
app = Dash(__name__)
app.layout = html.Div([
html.Div(children=[
html.Button('add Chart', id='add-chart', n_clicks=0)
]),
html.Div(id='container', children=[])
])
@app.callback(
Output('container', 'children'),
[Input('add-chart', 'n_clicks'),
Input({'type': 'remove-btn', 'index': ALL}, 'n_clicks')],
[State('container', 'children')],
prevent_initial_call=True
)
def display_graphs(n_clicks, n, div_children):
ctx = dash.callback_context
triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]
elm_in_div = len(div_children)
if triggered_id == 'add-chart':
new_child = html.Div(
id={'type': 'div-num', 'index': elm_in_div},
style={'width': '25%',
'display': 'inline-block',
'outline': 'none',
'padding': 5},
children=[
dbc.Container([
dbc.Row([
dbc.Col([dcc.Dropdown(id={'type': 'dataset-choice', 'index': n_clicks},
options=['dataset1'],
clearable=True,
value=[]
)], width=6),
dbc.Col([dcc.Dropdown(id={'type': 'feature-choice', 'index': n_clicks},
options=[],
multi=True,
clearable=True,
value=[]
)], width=6)
]),
dbc.Row([
dbc.Col([dcc.Graph(id={'type': 'dynamic-graph','index': n_clicks},
figure={}
)])
]),
dbc.Row([
dbc.Col([html.Button("Remove", id={'type': 'remove-btn', 'index': elm_in_div})
])
]),
])
]
)
div_children.append(new_child)
return div_children
if triggered_id != 'add-chart':
for idx, val in enumerate(n):
if val is not None:
del div_children[idx]
return div_children
@app.callback(
Output({'type': 'feature-choice', 'index': MATCH}, 'options'),
[Input({'type': 'dataset-choice', 'index': MATCH}, 'value')],
prevent_initial_call=True
)
def set_dataset_options(chosen_dataset):
if chosen_dataset is None:
return dash.no_update
else:
path = 'C:/Users/pymnb/OneDrive/Desktop/test/'
df = pd.read_csv(path + chosen_dataset+'.csv')
features = df.columns.values[0:2]
return features
@app.callback(
Output({'type': 'dynamic-graph', 'index': MATCH}, 'figure'),
[Input({'type': 'dataset-choice', 'index': MATCH}, 'value'),
Input({'type': 'feature-choice', 'index': MATCH}, 'value')],
prevent_initial_call=True
)
def update_graph(chosen_dataset1, chosen_feature):
if chosen_feature is None:
return dash.no_update
if chosen_dataset1 is None:
return dash.no_update
path = 'C:/Users/pymnb/OneDrive/Desktop/test/'
df = pd.read_csv(path + chosen_dataset1+'.csv')
Xmin = df[chosen_feature].min().min()
print(Xmin)
Xmax = df[chosen_feature].max().max()
# to find the height of y-axis(col4)
col4_max = df['col4'].max()
col4_min = df['col4'].min()
fig1 = px.line(df, x=chosen_feature, y='col4')
fig1.update_layout({'height': 600,
'legend': {'title': '', 'x': 0, 'y': 1.06, 'orientation': 'h'},
'margin': {'l': 0, 'r': 20, 't': 50, 'b': 0},
'paper_bgcolor': 'black',
'plot_bgcolor': 'white',
}
)
fig1.update_yaxes(range=[col4_max, col4_min], showgrid=False)
fig1.update_xaxes(showgrid=False)
categ_col3 = df.col3.dropna().unique()
colors = ['#54FF9F', '#87CEFF']
for (i,j) in zip(categ_col3, colors):
index_min = df.loc[df.col3 == i].index[0]
index_max = df.loc[df.col3 == i].index[-1]
if index_min == 0:
cat_min = df['col4'][index_min]
else:
cat_min = df['col4'][index_min-1]
cat_max = df['col4'][index_max]
fig1.add_shape(type="rect", x0=Xmin, y0=cat_min, x1=Xmax, y1=cat_max,
fillcolor=j, layer='below', opacity=0.5,
)
return fig1
if __name__ == '__main__':
app.run_server(debug=True)