I'm aiming to plot multiple graphs in a dbc.Container that can be manipulated with various filtering controls. The following app layout includes a DatePickerRange
for dates, Dropdown
for days of the week, and a Checklist
for unique values.
I aiming to plot two distinct bar charts that use DATE
and Type
columns. I'm also attempting to link both figures to ALL filtering options so any alteration will influence both bar charts at the same time.
I've attempted to achieve this using separate callbacks but only DATE
bar chart is plotted. The filtering options currently has no interactivity.
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
import dash
from dash.dependencies import Input, Output, State
from datetime import datetime
import plotly.graph_objs as go
import plotly.express as px
import pandas as pd
import numpy as np
from datetime import datetime as dt
df = pd.DataFrame({
'Type': ['A','B','B','C','D','D','E','E','F'],
})
N = 30
df = pd.concat([df] * N, ignore_index=True)
df['TIMESTAMP'] = pd.date_range(start='2022/01/01 07:30', end='2022/01/30 08:30', periods=len(df))
df['TIMESTAMP'] = pd.to_datetime(df['TIMESTAMP'], dayfirst = True).sort_values()
df['TIMESTAMP'] = df['TIMESTAMP'].dt.floor('1min')
df['DATE'], df['TIME'] = zip(*[(d.date(), d.time()) for d in df['TIMESTAMP']])
df['DATE'] = pd.to_datetime(df['DATE'])
df['YEAR'] = df['DATE'].dt.year
df = df.sort_values(by = 'DATE')
df['DOW'] = df['DATE'].dt.weekday
df = df.sort_values('DOW').reset_index(drop=True)
df['DOW'] = df['DATE'].dt.day_name()
external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP]
app = dash.Dash(__name__, external_stylesheets = external_stylesheets)
filter_box = html.Div(children=[
################### Filter box ######################
html.Div(children=[
html.Label('Filter by date (D-M-Y):'),
dcc.DatePickerRange(
id='input_date',
month_format='DD/MM/YYYY',
show_outside_days=True,
minimum_nights=0,
initial_visible_month=dt(2022, 1, 1),
min_date_allowed=dt(2016, 1, 1),
max_date_allowed=dt(2022, 12, 31),
start_date=dt.strptime("2022-01-01", "%Y-%m-%d").date(),
end_date=dt.strptime("2022-12-31", "%Y-%m-%d").date()
),
html.Label('Day of the week:', style={'paddingTop': '2rem'}),
dcc.Dropdown(
id='DOW',
options=[
{'label': 'Sun', 'value': '1'},
{'label': 'Mon', 'value': '2'},
{'label': 'Tue', 'value': '3'},
{'label': 'Wed', 'value': '4'},
{'label': 'Thurs', 'value': '5'},
{'label': 'Fri', 'value': '6'},
{'label': 'Sat', 'value': '7'}
],
value=['1', '2', '3', '4', '5', '6', '7'],
multi=True
),
html.Label('Type:', style={'paddingTop': '2rem', 'display': 'inline-block'}),
dcc.Checklist(
id='Type',
options=[
{'label': 'A', 'value': '1'},
{'label': 'B', 'value': '2'},
{'label': 'C', 'value': '3'},
{'label': 'D', 'value': '4'},
{'label': 'E', 'value': '5'},
{'label': 'F', 'value': '6'},
],
value=['1', '2', '3', '4', '5', '6'],
),
], className="four columns",
style={'padding':'2rem', 'margin':'1rem'} )
])
success_card = dbc.Card(
[
dbc.CardHeader("Some header"),
dbc.CardBody(
[
html.H6("Type Count"),
html.Div(id='count_of_types', style={"color": "Purple"})
]
),
],
className='text-center m-4'
)
failure_card = dbc.Card(
[
dbc.CardHeader("Some header"),
dbc.CardBody(
[
html.H6("Date Count"),
html.Div(id='count_of_dates', style={"color": "Black"})
]
),
],
className='text-center m-4'
)
app.layout = dbc.Container([
dbc.Row([
dbc.Col(html.Div(filter_box, className="bg-secondary h-100"), width=2),
dbc.Col([
dbc.Row([
dbc.Col(success_card),
]),
dbc.Row([
dbc.Col(dcc.Graph(id = 'date-bar-chart'), style={
"padding-bottom": "10px",
},),
]),
dbc.Row([
# insert pie chart
dbc.Col(dcc.Graph(id = "type-bar-chart")),
]),
], width=5),
dbc.Col([
dbc.Row([
dbc.Col(failure_card),
]),
dbc.Row([
# insert bar chart
dbc.Col(dcc.Graph()),
], className="h-100"),
], width=5),
])
], fluid=True)
@app.callback(
Output('type-bar-chart', 'figure'),
[Input("Type", "value")
])
@app.callback(
Output('date-bar-chart', 'figure'),
[Input("DOW", "value")
])
def date_chart(value):
#bar_data = df[df['DOW'] == value]
count = df['DOW'].value_counts()
data = go.Bar(x = count.index, y = count.values)
layout = go.Layout(title = 'DOW')
fig = go.Figure(data = data, layout = layout)
return fig
def type_chart(value):
#bar_data = df[df['Type'] == value]
count = df['Type'].value_counts()
data = go.Bar(x = count.index, y = count.values)
layout = go.Layout(title = 'Type')
fig = go.Figure(data = data, layout = layout)
return fig
if __name__ == '__main__':
app.run_server(debug=True, port = 8051)
Intended output:
Type bar chart should be displayed as the bottom left figure (not DOW
).
Filter box containing DatePickerRange
for dates, Dropdown
for days of the week, and a Checklist
for unique values in Type
should interact simultaneously with both figures (DOW
,Type
)
I saw that you did not filter your dataframe with filters and then use it to return graphs so that it did not work. I think you should revise your code as below to make it work.
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
import dash
from dash.dependencies import Input, Output, State
from datetime import datetime
import plotly.graph_objs as go
import plotly.express as px
import pandas as pd
import numpy as np
from datetime import datetime as dt
df = pd.DataFrame({
'Type': ['A','B','B','C','D','D','E','E','F'],
})
N = 30
df = pd.concat([df] * N, ignore_index=True)
df['TIMESTAMP'] = pd.date_range(start='2022/01/01 07:30', end='2022/01/30 08:30', periods=len(df))
df['TIMESTAMP'] = pd.to_datetime(df['TIMESTAMP'], dayfirst = True).sort_values()
df['TIMESTAMP'] = df['TIMESTAMP'].dt.floor('1min')
df['DATE'], df['TIME'] = zip(*[(d.date(), d.time()) for d in df['TIMESTAMP']])
df['DATE'] = pd.to_datetime(df['DATE'])
df['YEAR'] = df['DATE'].dt.year
df = df.sort_values(by = 'DATE')
df['DOW'] = df['DATE'].dt.weekday
df = df.sort_values('DOW').reset_index(drop=True)
df['DOW'] = df['DATE'].dt.day_name()
external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP]
app = dash.Dash(__name__, external_stylesheets = external_stylesheets)
filter_box = html.Div(children=[
################### Filter box ######################
html.Div(children=[
html.Label('Filter by date (D-M-Y):'),
dcc.DatePickerRange(
id='input_date',
month_format='DD/MM/YYYY',
show_outside_days=True,
minimum_nights=0,
initial_visible_month=dt(2022, 1, 1),
min_date_allowed=dt(2016, 1, 1),
max_date_allowed=dt(2022, 12, 31),
start_date=dt.strptime("2022-01-01", "%Y-%m-%d").date(),
end_date=dt.strptime("2022-12-31", "%Y-%m-%d").date()
),
html.Label('Day of the week:', style={'paddingTop': '2rem'}),
dcc.Dropdown(
id='DOW',
options=[
{'label': x, 'value': x} for x in df['DOW'].unique()
],
value=['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday','Sunday'],
multi=True
),
html.Label('Type:', style={'paddingTop': '2rem', 'display': 'inline-block'}),
dcc.Checklist(
id='Type',
options=[
{'label': 'A', 'value': 'A'},
{'label': 'B', 'value': 'B'},
{'label': 'C', 'value': 'C'},
{'label': 'D', 'value': 'D'},
{'label': 'E', 'value': 'E'},
{'label': 'F', 'value': 'F'},
],
value=['A', 'B', 'C', 'D', 'E', 'F'],
),
], className="four columns",
style={'padding':'2rem', 'margin':'1rem'} )
])
success_card = dbc.Card(
[
dbc.CardHeader("Some header"),
dbc.CardBody(
[
html.H6("Type Count"),
html.Div(id='count_of_types', style={"color": "Purple"})
]
),
],
className='text-center m-4'
)
failure_card = dbc.Card(
[
dbc.CardHeader("Some header"),
dbc.CardBody(
[
html.H6("Date Count"),
html.Div(id='count_of_dates', style={"color": "Black"})
]
),
],
className='text-center m-4'
)
app.layout = dbc.Container([
dbc.Row([
dbc.Col(html.Div(filter_box, className="bg-secondary h-100"), width=2),
dbc.Col([
dbc.Row([
dbc.Col(success_card),
]),
dbc.Row([
dbc.Col(dcc.Graph(id = 'date-bar-chart'), style={
"padding-bottom": "10px",
},),
]),
dbc.Row([
# insert pie chart
dbc.Col(dcc.Graph(id = "type-bar-chart")),
]),
], width=5),
dbc.Col([
dbc.Row([
dbc.Col(failure_card),
]),
dbc.Row([
# insert bar chart
dbc.Col(dcc.Graph()),
], className="h-100"),
], width=5),
])
], fluid=True)
@app.callback(
Output('date-bar-chart', 'figure'),
[Input('input_date','start_date'),
Input('input_date','end_date'),
Input("DOW", "value"),
Input("Type", "value")])
def date_chart(start_date, end_date, dow, types):
dff= df[(df['DATE'] >= start_date)&(df['DATE'] <= end_date)]
dff = dff[dff['DOW'].isin(dow)]
dff = dff[dff['Type'].isin(types)]
count = dff['DOW'].value_counts()
data = go.Bar(x = count.index, y = count.values)
layout = go.Layout(title = 'DOW')
fig = go.Figure(data = data, layout = layout)
return fig
@app.callback(
Output('type-bar-chart', 'figure'),
[Input('input_date','start_date'),
Input('input_date','end_date'),
Input("DOW", "value"),
Input("Type", "value")])
def date_chart(start_date, end_date, dow, types):
dff= df[(df['DATE'] >= start_date)&(df['DATE'] <= end_date)]
dff = dff[dff['DOW'].isin(dow)]
dff = dff[dff['Type'].isin(types)]
count = dff['Type'].value_counts()
data = go.Bar(x = count.index, y = count.values)
layout = go.Layout(title = 'Type')
fig = go.Figure(data = data, layout = layout)
return fig
if __name__ == '__main__':
app.run_server(debug=False, port = 8051)