Getting ValueError: ('Lengths must match to compare', (36,), (1,)) - python

Month dropdown list unable to display value according to the year selected.
Error message:
ValueError: ('Lengths must match to compare', (36,), (1,))
I had a year dropdown list, require to display the month list based on the year selected and the date list according to the month selected.
Date: 01/02/2021, 29/02/2021, 20/12/2021, 05/06/2021, 25/07/2021, 01/05/2022, 20/03/2022, 21/09/2022, 30/07/2022
Year list : 2021, 2022
Year selected: 2021
Month list: Feb, June, July, Dec
Month selected: Feb
Date list: 01/02/2021, 29/02/2021
Code:
df['year'] = pd.to_datetime(df['Date'], format = '%d/%m/%Y', errors='coerce').dt.year
month_labels = {1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr', 5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Aug',9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dec'}
df['month'] = pd.to_datetime(df['Date'], format = '%d/%m/%Y', errors='coerce').dt.month
df['monthname']= df['month'].apply(lambda x: month_labels[x])
df['date'] = pd.to_datetime(df['Date'], format = '%d/%m/%Y', errors='coerce')
df.sort_values(by= ['year', 'month', 'Date'], inplace = True)
month_cat = list(df['monthname'].unique())
sort_mm = sorted(month_cat, key=lambda m: datetime.strptime(m, "%b"))
sort_yr = df['year'].drop_duplicates()
dbc.Row([
dbc.Col([
html.H3('Year'),
html.Br(),
dcc.Dropdown(id='year_dd', value= [df['year'].max()],
options = [{'label':x, 'value':x}
for x in sort_yr],
),
html.Br(),
html.H3('Month'),
html.Br(),
dcc.Dropdown(id='month_dd', value= ''
)
#create month selection based on year
#app.callback(
Output('month_dd','options'),
Input('year_dd', 'value')
)
def update_dd (year_dd):
year_month= df.drop_duplicates(['Date'], inplace= False)
relevant_month= year_month[df['year'] == year_dd]['monthname'].values.tolist()
month_opt= [dict(label=x,value=x)for x in relevant_month]
return month_opt
#set latest date as default value according to month dropdown
#app.callback(
Output('month_dd','value'),
Input('month_dd', 'options')
)
def default_value(latest_date):
monthvalue = latest_date[-1]['value']
return monthvalue
####### can ignore this part, is just a reference ############
#create date dropdown according to month dropdown
#app.callback(
Output('date_dd','options'),
Input('month_dd', 'value')
)
def update_dd (month_dd):
month_date= df.drop_duplicates(['Date'], inplace= False)
relevant_date= month_date[df['monthname'] == month_dd]['Date'].values.tolist()
date_option= [dict(label=x,value=x)for x in relevant_date]
return date_option
#set latest date as default value according to month dropdown
#app.callback(
Output('date_dd','value'),
Input('date_dd', 'options')
)
def default_value(latest_date):
datevalue = latest_date[-1]['value']
return datevalue

Related

Plotly Dash `px.bar` not updating in callback function

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

Callback not working for Dropdown in Plotly Dash

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!

Display all previous month data with the selected date's data in python chart

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?

SQL Database auto update python

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

dash dynamically generating graphs in tabs

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

Categories

Resources