Related
The graph in the app.layout is not updated at callback. Code is shown below, however, it requires a csv file of data that is turned into a pandas.Dataframe. I will post the first 26 rows here for reference. (This is a subset of results of the Houston Marathon that took place on the Saturday of the 15th of Jan!)
The code takes datetime.time data, bins it into 5 minutes of length, before creating a histogram in px.bar. Given a user's time input - their percentile in the sample distribution is visualized.
place,name,time
1,Dominic Ondoro,02:10:36
2,Tsedat Ayana,02:10:37
3,Teshome Mekonen,02:11:05
4,Parker Stinson,02:12:11
5,Tyler Pennel,02:12:16
6,Kenta Uchida,02:14:13
7,James Ngandu,02:14:28
8,Alvaro Abreu,02:14:28
9,Kevin Salvano,02:16:39
10,Tyler Pence,02:16:44
11,Phillip Reid,02:16:46
12,Mark Messmer,02:17:27
13,Shadrack Biwott,02:17:36
14,Hitomi Niiya,02:19:24
15,David Fuentes,02:20:28
16,Patrice Labonte,02:20:49
17,Joseph Niemiec,02:21:06
18,Jesse Joseph,02:21:09
19,Aaron Davidson,02:21:40
20,Stan Linton,02:21:43
21,Mitchell Klingler,02:21:53
22,Michael Babinec,02:22:52
23,Tom Derr,02:23:07
24,Matt Dynan,02:23:33
25,Alexander Diltz,02:23:41
CSV_FILE_NAME = 'houston_marathon_2023.csv'
# Contents of the CSV file are above
def parse_data_as_df():
df = pd.read_csv(CSV_FILE_NAME, encoding='latin-1')
df['time'] = pd.to_datetime(df['time']).dt.time
return df
def create_histogram(cutoff_time):
BIN_SIZE_MINUTES = 5
MIN_TIME = dt.time(hour=2, minute=0, second=0)
MAX_TIME = dt.time(hour=6, minute=10, second=0)
time_increment = MIN_TIME
time_bins = {}
data = parse_data_as_df()
# get bins for original
while time_increment <= MAX_TIME:
next_time = dt.time(hour=time_increment.hour + int((time_increment.minute + BIN_SIZE_MINUTES) / 60),
minute=(time_increment.minute + BIN_SIZE_MINUTES) % 60,
second=0)
time_bins[time_increment] = 0
for a_time in data['time']:
if time_increment <= a_time < next_time:
time_bins[time_increment] += 1/len(data['time'])
time_increment = next_time
df = pd.DataFrame({'bin_times': time_bins.keys(), 'percent': time_bins.values()})
df["color"] = np.select(
[df["bin_times"].lt(cutoff_time)],
["#fd7e14"],
"#158cba",
)
load_figure_template(['lumen'])
fig = px.bar(
df,
x="bin_times",
y="percent",
color="color",
color_discrete_map={
"#fd7e14": "#fd7e14",
"#158cba": "#158cba",
},
template='lumen',
hover_data={
'color': False,
'percent': ':.1%'
}
)
fig.update_xaxes(tickformat='%H:%M',
ticktext=[d.strftime('%H:%M') for d in df['bin_times']])
fig.update_yaxes(tickformat='0%',
range=[0, 0.05])
fig.update_layout(xaxis_title="Time (HH:MM)",
yaxis_title="Density (%)",
showlegend=False,
bargap=0.025)
return fig
def create_dash_application():
APP_STYLESHEET = "https://cdn.jsdelivr.net/npm/bootswatch#5.2.3/dist/lux/bootstrap.min.css"
DEFAULT_CUTOFF_TIME = dt.time(hour=3)
dash_app = Dash(__name__, external_stylesheets=[APP_STYLESHEET])
dash_app.layout = html.Div([
html.Br(),
dcc.Graph(id='histogram_graph',
figure=create_histogram(DEFAULT_CUTOFF_TIME),
config={'displayModeBar': False},
animate=True),
html.Br(),
html.Div(
[
html.B('Hours: '),
dcc.Input(id='time_hours', value='', type='text', style={'width': '25%'}),
]),
html.Br(),
html.Div(
[
html.B('Minutes: '),
dcc.Input(id='time_minutes', value='', type='text', style={'width': '25%'}),
]),
html.Br(),
html.Div(
[
html.B('Seconds: '),
dcc.Input(id='time_seconds', value='', type='text', style={'width': '25%'}),
]),
html.Br(),
html.Button(children='Analyse', id='button_submit', n_clicks=0, style={'width': '25%'}, type='button'),
], style={'width': '75%'})
#dash_app.callback(
Output('histogram_graph', 'figure'),
[Input('button_submit', 'n_clicks'),
Input('time_hours', 'value'),
Input('time_minutes', 'value'),
Input('time_seconds', 'value')],
prevent_initial_call=True)
def update_output(n_clicks, the_hours, the_minutes, the_seconds):
if n_clicks > 0 and the_hours != '' and the_minutes != '' and the_seconds != '':
in_time = dt.time(hour=int(the_hours), minute=int(the_minutes), second=int(the_seconds))
# Something wrong here, as histogram is correctly generated but not changed in Dash App
return create_histogram(cutoff_time=in_time)
else:
return None
dash_app.run_server(debug=True)
create_dash_application()
I've isolated the issue to the callback returning a correct fig, that is not being updated in the app.layout. It is not an issue in the creation of fig, as confirmed by observing fig.show().
I am expecting fig in dcc.Graph to be updated.
What am I missing?
If you want to use the button to run the inputs, you need to switch those inputs to State. Please use below code to run:
import datetime as dt
import dash
CSV_FILE_NAME = 'houston_marathon_2023.csv'
# Contents of the CSV file are above
def parse_data_as_df():
df = pd.read_csv(CSV_FILE_NAME, encoding='latin-1')
df['time'] = pd.to_datetime(df['time']).dt.time
return df
def create_histogram(cutoff_time):
BIN_SIZE_MINUTES = 5
MIN_TIME = dt.time(hour=2, minute=0, second=0)
MAX_TIME = dt.time(hour=6, minute=10, second=0)
time_increment = MIN_TIME
time_bins = {}
data = parse_data_as_df()
# get bins for original
while time_increment <= MAX_TIME:
next_time = dt.time(hour=time_increment.hour + int((time_increment.minute + BIN_SIZE_MINUTES) / 60),
minute=(time_increment.minute + BIN_SIZE_MINUTES) % 60,
second=0)
time_bins[time_increment] = 0
for a_time in data['time']:
if time_increment <= a_time < next_time:
time_bins[time_increment] += 1/len(data['time'])
time_increment = next_time
df = pd.DataFrame({'bin_times': time_bins.keys(), 'percent': time_bins.values()})
df["color"] = np.select(
[df["bin_times"].lt(cutoff_time)],
["#fd7e14"],
"#158cba",
)
fig = px.bar(
df,
x="bin_times",
y="percent",
color="color",
color_discrete_map={
"#fd7e14": "#fd7e14",
"#158cba": "#158cba",
},
hover_data={
'color': False,
'percent': ':.1%'
}
)
fig.update_xaxes(tickformat='%H:%M',
ticktext=[d.strftime('%H:%M') for d in df['bin_times']])
fig.update_yaxes(tickformat='0%',
range=[0, 0.05])
fig.update_layout(xaxis_title="Time (HH:MM)",
yaxis_title="Density (%)",
showlegend=False,
bargap=0.025)
return fig
def create_dash_application():
APP_STYLESHEET = "https://cdn.jsdelivr.net/npm/bootswatch#5.2.3/dist/lux/bootstrap.min.css"
DEFAULT_CUTOFF_TIME = dt.time(hour=3)
dash_app = dash.Dash(__name__, external_stylesheets=[APP_STYLESHEET])
dash_app.layout = html.Div([
html.Br(),
dcc.Graph(id='histogram_graph',
figure=create_histogram(DEFAULT_CUTOFF_TIME),
config={'displayModeBar': False},
animate=True),
html.Br(),
html.Div(
[
html.B('Hours: '),
dcc.Input(id='time_hours', value='', type='text', style={'width': '25%'}),
]),
html.Br(),
html.Div(
[
html.B('Minutes: '),
dcc.Input(id='time_minutes', value='', type='text', style={'width': '25%'}),
]),
html.Br(),
html.Div(
[
html.B('Seconds: '),
dcc.Input(id='time_seconds', value='', type='text', style={'width': '25%'}),
]),
html.Br(),
html.Button(children='Analyse', id='button_submit', n_clicks=0, style={'width': '25%'}, type='button'),
], style={'width': '75%'})
#dash_app.callback(
Output('histogram_graph', 'figure'),
[Input('button_submit', 'n_clicks')],
[State('time_hours', 'value'),
State('time_minutes', 'value'),
State('time_seconds', 'value')],
prevent_initial_call=True)
def update_output(n_clicks, the_hours, the_minutes, the_seconds):
if n_clicks > 0 and the_hours != '' and the_minutes != '' and the_seconds != '':
in_time = dt.time(hour=int(the_hours), minute=int(the_minutes), second=int(the_seconds))
# Something wrong here, as histogram is correctly generated but not changed in Dash App
return create_histogram(cutoff_time=in_time)
else:
return None
dash_app.run_server(debug=True)
create_dash_application()
Hope this help
I am trying to create an UI that allows to select a date range and displays the total number of users in that date range.
Also, it allows to select a time frame and gives a plot of number of users per time frame.
For example, if 01/01/2021 to 01/01/2022 is selected, the UI will show the total number of users in that date range. Also, if a time frame of 'Per Week' is selected then a plot of number of users per week between the given date range is generated.
For choosing date range, I have used DateRangePicker and for choosing time frame, I have used a Dropdown component.
This seems to be working fine except for the callback for Dropdown. The dropdown gives the correct plot for a chosen time frame, but when value of the dropdown is changed, the plot shows no changes at all. If I refresh the page and choose a different value in dropdown, the plot gets generated just fine.
Here is the app layout :
app = dash.Dash()
app.layout = dhc.Div([
dhc.H1(children = 'Web Analytics Template',
style = {
'textAlign' : 'center',
'color' : 'Black'
}),
dhc.Div(children = 'Website Overview',
style = {
'textAlign' : 'left',
'color' : 'Black',
'font-size' : 'larger'
}),
dhc.Div(children = 'Select A Date Range',
style = {
'textAlign' : 'left',
'color' : 'Black',
'font-size' : 'larger'
}),
dcc.DatePickerRange(
id = 'Date_Range',
min_date_allowed = date(int(min_date[0 : 4]), int(min_date[4 : 6]), int(min_date[6 : ])),
max_date_allowed = date(int(max_date[0 : 4]), int(max_date[4 : 6]), int(max_date[6 : ]))
),
dhc.Div(children = 'Total Visitors'),
dhc.Br(),
dhc.Div(id = 'total_users'),
dhc.Div(children = 'Select A Time Frame To See A Plot Of No. Of Visitors'),
dcc.Dropdown(
options = ['Per Day', 'Per Week', 'Per Month', 'Per Year'], id = 'Time_Frame_Dropdown'
),
dhc.Div(id = 'users_per_time_frame')
])
And here are the callbacks and functions. The function 'users_per_time_frame' is used to plot the number of visitors per time frame.
#app.callback(
Output(component_id = 'total_users', component_property = 'children'),
Input(component_id = 'Date_Range', component_property = 'start_date'),
Input(component_id = 'Date_Range', component_property = 'end_date'))
def total_users (start_date, end_date):
if start_date == '' and end_date == '':
total_users = len(pd.unique(data['user_pseudo_id']))
elif start_date != '' and end_date == '':
total_users = len(pd.unique(data['user_pseudo_id'].where(data['event_date'] >= start_date)))
elif start_date == '' and end_date != '':
total_users = len(pd.unique(data['user_pseudo_id'].where(data['event_date'] <= end_date)))
elif start_date != '' and end_date != '':
total_users = len(pd.unique(data['user_pseudo_id'].where((data['event_date'] >= start_date) & (data['event_date'] <= end_date))))
return total_users
#app.callback(
Output(component_id = 'users_per_time_frame', component_property = 'children'),
Input(component_id = 'Time_Frame_Dropdown', component_property = 'value'))
def users_per_time_frame (value):
if value == 'Per Day':
users_per_time_frame = data[['user_pseudo_id', 'event_date']].groupby(['event_date']).nunique()
if value == 'Per Week':
users_per_time_frame = data[['user_pseudo_id', 'Year', 'Month', 'Week']].groupby(['Year', 'Month', 'Week']).nunique()
if value == 'Per Month':
users_per_time_frame = data[['user_pseudo_id', 'Year', 'Month']].groupby(['Year', 'Month']).nunique()
if value == 'Per Year':
users_per_time_frame = data[['user_pseudo_id', 'Year']].groupby(['Year']).nunique()
return dcc.Graph(
id = 'users_per_time_frame',
figure = {
'data' : [
{'x' : users_per_time_frame.index, 'y' : users_per_time_frame.user_pseudo_id, 'type' : 'line', 'name' : 'Visitors'}
],
'layout' : {
'plot_bgcolor' : 'black',
'paper_bgcolor' : 'grey',
'title' : 'Visitors'
}
})
Thanks in advance!
How to display all the previous month data with the selected date's data in plotly python?
Let says selected date, 15/03/2022, so, the bar chart should show all the previous whole month data (Jan, Feb) and for Mar, data should be show month-to-date data (01/03/2022 to 15/03/2022).
This is what I can get now, but it is not what I want. For Jan and Feb, the data is correct as it taking the whole month data, but for the Mar, it also taking the whole month data instead of month-to-date.
enter image description here
Code as per below:
(1) this code will get month-to-date data (01/03/2022 to 15/03/2022)
month_category = list(df['Month'].unique())
date_category = list(df['Settlement_Date'].unique())
bar_groupby = df.groupby(['Settlement_Date','Date','Month'])['MTD'].agg(['sum']).reset_index().rename(columns={'sum':'Total_Tx_Amount'})
app.layout = dbc.Container([
dbc.Row([
dbc.Col([
html.H3('Month'),
html.Br(),
dcc.Dropdown(id='month_dd', value= 'Jan',
options = [{'label':x, 'value':x}
for x in month_category],
searchable = True, search_value='',
placeholder= 'Please select ...'
),
html.Br(),
html.H3('Date'),
html.Br(),
dcc.Dropdown(id='date_dd')
])
]),
dbc.Row([
dbc.Col([
html.P("Bar Chart:",
style={"textDecoration":"underline"}),
dcc.Graph(id='bar-fig', figure={})
])
])
])
#app.callback(
Output('date_dd','options'),
Input('month_dd', 'value')
)
def update_dd (month_dd):
month_date= df.drop_duplicates(['Month','Settlement_Date'], inplace= False)
relevant_date= month_date[month_date['Month']== month_dd]['Settlement_Date'].values.tolist()
date_option= [dict(label=x,value=x)for x in relevant_date]
return date_option
#app.callback(
Output('bar-fig', 'figure'),
Input('date_dd', 'value')
)
def update_graph(selection):
if len (selection) ==0:
return dash.no_update
else:
dff = bar_groupby[bar_groupby['Settlement_Date'] == selection]
fig = px.bar(dff, x='Month', y='Total_Tx_Amount', title='Bar_chart', color='Month')
return fig
(2) this code will get data for all the month (Jan, Feb, Mar)
month_category = list(df['Month'].unique())
date_category = list(df['Settlement_Date'].unique())
bar_groupby = df.groupby(['Settlement_Date','Date','Month'])['MTD'].agg(['sum']).reset_index().rename(columns={'sum':'Total_Tx_Amount'})
app.layout = dbc.Container([
dbc.Row([
dbc.Col([
html.H3('Month'),
html.Br(),
dcc.Dropdown(id='month_dd', value= 'Jan',
options = [{'label':x, 'value':x}
for x in month_category],
searchable = True, search_value='',
placeholder= 'Please select ...'
),
html.Br(),
html.H3('Date'),
html.Br(),
dcc.Dropdown(id='date_dd')
])
]),
dbc.Row([
dbc.Col([
html.P("Bar Chart:",
style={"textDecoration":"underline"}),
dcc.Graph(id='bar-fig', figure={})
])
])
])
#app.callback(
Output('date_dd','options'),
Input('month_dd', 'value')
)
def update_dd (month_dd):
month_date= df.drop_duplicates(['Month','Settlement_Date'], inplace= False)
relevant_date= month_date[month_date['Month']== month_dd]['Settlement_Date'].values.tolist()
date_option= [dict(label=x,value=x)for x in relevant_date]
return date_option
#app.callback(
Output('bar-fig', 'figure'),
Input('date_dd', 'value')
)
def update_graph(selection):
if len (selection) ==0:
return dash.no_update
else:
fig = px.bar( bar_groupby, x='Month', y='Total_Tx_Amount', title='Bar_chart', color='Month')
return fig
both code getting the correct data, but I m not able to join both data into a same chart.
Can anyone assist or advise on this?
engine = sqlalchemy.create_engine('sqlite:///CRYPTO.db')
client = Client()
info = client.get_exchange_info()
# Create empty dict and get klines in iteration
columns = [
'Time', 'Open', 'High', 'Low', 'Close', 'Volume', 'Close Time', 'Asset Volume',
'Number Of Trades', 'Buy Base', 'Buy Quote', 'Ignore',
]
klines = {}
for symbol in USDTsymbol:
r_klines = client.get_historical_klines(
symbol, Client.KLINE_INTERVAL_1MONTH,
"1 April 2018", "1 DEC, 2020"
)
r_klines2 = client.get_historical_klines(
symbol, Client.KLINE_INTERVAL_1WEEK,
"1 JAN 2021", "1 JUNE, 2021"
df = pd.DataFrame(r_klines + r_klines2, columns=columns)
klines[symbol] = df
print(df)
df.Time = pd.to_datetime(df.Time, unit='ms')
for df in klines:
data = klines[df]
data[columns].to_sql(symbol, engine, if_exists='replace')
-How to update database from last left off instead of redownloading data?
-->Will appreciate your help. Thank you
I have a dropdown list of Indian states. Upon selecting one state, different graphs should be generated under different tabs. I want to generate a total of 6 graphs and 3 tabs namely, 'convicts', 'under_trial', 'detenues'. Each of these tabs will contain 2 graphs each.
The graphs are gender and caste distribution of convicts gender and caste distribution of under_trial gender and caste distribution of detenues based on the dropdown value of the Indian state selected.
I want to create something like this.
Here is the dataset used.
Libraries imported
import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
import plotly.express as px
Dash web app initialization
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
Pandas dataframe loading
df = pd.read_csv("Caste.csv")
Defined dropdown and graph functions
def dropdown():
return html.Div([dcc.Dropdown(id='dropdown',
options=[{'label': i, 'value': i} for i in df["state_name"].unique()],
value="Gujarat")]
,className="dropdown")
def graph1_convicts():
return dcc.Graph(id="graph1_convicts")
def graph2_convicts():
return dcc.Graph(id="graph2_convicts")
def graph1_under_trial():
return dcc.Graph(id="graph1_under_trial")
def graph2_under_trial():
return dcc.Graph(id="graph2_under_trial")
def graph1_detenues():
return dcc.Graph(id="graph1_detenues")
def graph2_detenues():
return dcc.Graph(id="graph2_detenues")
Layout
app.layout = dbc.Container([
dbc.Row([dbc.Col([html.Div("Indian Prison Stats between 2001-2013", className="heading")])]),
dbc.Row([dbc.Col(dropdown())]),
dcc.Tabs(id="tabs-selector",
value="tab-1",
className="custom-tabs-container",
children=[
dcc.Tab(label="Convicts",
value="tab-1",
className="custom-tab",
children=[html.Div([graph1_convicts(),
html.Br(),
graph2_convicts()]),
]),
dcc.Tab(label="under_trial",
value="tab-2",
className="custom-tab",
children=[html.Div([graph1_under_trial(),
html.Br(),
graph2_under_trial()]),
]),
dcc.Tab(label="detenues",
value="tab-3",
className="custom-tab",
children=[html.Div([graph1_detenues(),
html.Br(),
graph2_detenues()]),
]),
]),
])
Callback
#app.callback([Output('graph1_convicts', 'figure'),
Output('graph2_convicts', 'figure'),
Output("graph1_under_trial", "figure"),
Output("graph2_under_trial", "figure"),
Output("graph1_detenues", "figure"),
Output("graph2_detenues", "figure")],
[Input('dropdown', 'value'),
Input("tabs-selector", "value")])
def update_graph(dropdown, tab):
# df1_convicts has only convicts column kept, rest all removed, and groupby is done on gender column
df1_convicts = df[df["state_name"]==dropdown]
df1_convicts = df1_convicts.drop(["is_state", "caste", "under_trial", "detenues", "others"], axis=1)
df1_convicts = df1_convicts.groupby(['state_name', "year", "gender"])['convicts'].sum().reset_index()
# df2_convicts has only convicts column kept, rest all removed, and groupby is done on caste column
df2_convicts = df[df["state_name"]==dropdown]
df2_convicts = df2_convicts.drop(["is_state", "gender", "under_trial", "detenues", "others"], axis=1)
df2_convicts = df2_convicts.groupby(["state_name", "year", "caste"])["convicts"].sum().reset_index()
# df1_under_trial has only under_trial column kept, rest all removed, and groupby is done on gender column
df1_under_trial = df[df["state_name"]==dropdown]
df1_under_trial = df1_under_trial.drop(["is_state", "caste", "convicts", "detenues", "others"], axis=1)
df1_under_trial = df1_under_trial.groupby(['state_name', "year", "gender"])['under_trial'].sum().reset_index()
# df2_under_trial has only under_trial column kept, rest all removed, and groupby is done on caste column
df2_under_trial = df[df["state_name"]==dropdown]
df2_under_trial = df2_under_trial.drop(["is_state", "gender", "convicts", "detenues", "others"], axis=1)
df2_under_trial = df2_under_trial.groupby(["state_name", "year", "caste"])["under_trial"].sum().reset_index()
# df1_detenues has only detenues column kept, rest all removed, and groupby is done on gender column
df1_detenues = df[df["state_name"]==dropdown]
df1_detenues = df1_detenues.drop(["is_state", "caste", "convicts", "under_trial", "others"], axis=1)
df1_detenues = df1_detenues.groupby(['state_name', "year", "gender"])['detenues'].sum().reset_index()
# df2_under_trial has only under_trial column kept, rest all removed, and groupby is done on caste column
df2_detenues = df[df["state_name"]==dropdown]
df2_detenues = df2_detenues.drop(["is_state", "gender", "convicts", "under_trial", "others"], axis=1)
df2_detenues = df2_detenues.groupby(["state_name", "year", "caste"])["detenues"].sum().reset_index()
fig1_convicts = px.bar(df1_convicts, x="year", y="convicts", color="gender", title="gender distribution of convicts",
color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
fig2_convicts = px.bar(df2_convicts, x="year", y="convicts", color="caste", title="caste distribution of convicts",
color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
fig1_under_trial = px.bar(df1_under_trial, x="year", y="under_trial", color="gender", title="gender distribution of under_trial",
color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
fig2_under_trial = px.bar(df2_under_trial, x="year", y="under_trial", color="caste", title="caste distribution of under_trial",
color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
fig1_detenues = px.bar(df1_detenues, x="year", y="detenues", color="gender", title="gender distribution of detenues",
color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
fig2_detenues = px.bar(df2_detenues, x="year", y="detenues", color="caste", title="caste distribution of detenues",
color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
if tab=="tab-1":
return fig1_convicts, fig2_convicts
elif tab=="tab-3":
return fig1_detenues, fig2_detenues
elif tab=="tab-2":
return fig1_under_trial, fig2_under_trial
if __name__ == '__main__':
app.run_server(debug=True, port=5050)
How do I define the callback?
I could easily create gender and caste distribution of either convicts or under_trial or detenues. But, I am confused about how to show all 6 graphs under the 3 tabs based on the dropdown value.
I searched online and found that dcc.State might be useful in this case, but I couldn't understand it properly.
first thing is that you need to return all the output you define in the callback.
in your case you need 6 outputs to this callback
now as I see it you have 2 options:
generate all the graphs when you change the dropdown it will work with the current contact layout
only hold 1 tab contact and dynamically create only 2 graph when you switch tabs
option 1 code should look like this:
#app.callback([Output('graph1_convicts', 'figure'),
Output('graph2_convicts', 'figure'),
Output("graph1_under_trial", "figure"),
Output("graph2_under_trial", "figure"),
Output("graph1_detenues", "figure"),
Output("graph2_detenues", "figure")],
[Input('dropdown', 'value')])
def update_graph(dropdown):
# df1_convicts has only convicts column kept, rest all removed, and groupby is done on gender column
df1_convicts = df[df["state_name"]==dropdown]
df1_convicts = df1_convicts.drop(["is_state", "caste", "under_trial", "detenues", "others"], axis=1)
df1_convicts = df1_convicts.groupby(['state_name', "year", "gender"])['convicts'].sum().reset_index()
# df2_convicts has only convicts column kept, rest all removed, and groupby is done on caste column
df2_convicts = df[df["state_name"]==dropdown]
df2_convicts = df2_convicts.drop(["is_state", "gender", "under_trial", "detenues", "others"], axis=1)
df2_convicts = df2_convicts.groupby(["state_name", "year", "caste"])["convicts"].sum().reset_index()
# df1_under_trial has only under_trial column kept, rest all removed, and groupby is done on gender column
df1_under_trial = df[df["state_name"]==dropdown]
df1_under_trial = df1_under_trial.drop(["is_state", "caste", "convicts", "detenues", "others"], axis=1)
df1_under_trial = df1_under_trial.groupby(['state_name', "year", "gender"])['under_trial'].sum().reset_index()
# df2_under_trial has only under_trial column kept, rest all removed, and groupby is done on caste column
df2_under_trial = df[df["state_name"]==dropdown]
df2_under_trial = df2_under_trial.drop(["is_state", "gender", "convicts", "detenues", "others"], axis=1)
df2_under_trial = df2_under_trial.groupby(["state_name", "year", "caste"])["under_trial"].sum().reset_index()
# df1_detenues has only detenues column kept, rest all removed, and groupby is done on gender column
df1_detenues = df[df["state_name"]==dropdown]
df1_detenues = df1_detenues.drop(["is_state", "caste", "convicts", "under_trial", "others"], axis=1)
df1_detenues = df1_detenues.groupby(['state_name', "year", "gender"])['detenues'].sum().reset_index()
# df2_under_trial has only under_trial column kept, rest all removed, and groupby is done on caste column
df2_detenues = df[df["state_name"]==dropdown]
df2_detenues = df2_detenues.drop(["is_state", "gender", "convicts", "under_trial", "others"], axis=1)
df2_detenues = df2_detenues.groupby(["state_name", "year", "caste"])["detenues"].sum().reset_index()
fig1_convicts = px.bar(df1_convicts, x="year", y="convicts", color="gender", title="gender distribution of convicts",
color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
fig2_convicts = px.bar(df2_convicts, x="year", y="convicts", color="caste", title="caste distribution of convicts",
color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
fig1_under_trial = px.bar(df1_under_trial, x="year", y="under_trial", color="gender", title="gender distribution of under_trial",
color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
fig2_under_trial = px.bar(df2_under_trial, x="year", y="under_trial", color="caste", title="caste distribution of under_trial",
color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
fig1_detenues = px.bar(df1_detenues, x="year", y="detenues", color="gender", title="gender distribution of detenues",
color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
fig2_detenues = px.bar(df2_detenues, x="year", y="detenues", color="caste", title="caste distribution of detenues",
color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
return fig1_convicts, fig2_convicts,
fig1_under_trial, fig2_under_trial,
fig1_detenues, fig2_detenues
for option 2 you can see https://dash.plotly.com/dash-core-components/tabs it is the first option in the examples