'Dash DatePickerRange with Graph
I am trying to connect a graph to a DatePickerRange. However, i keep running into a problem, when trying to connect the graph and date picker. I have the following code:
import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from datetime import datetime
import plotly.graph_objs as go
import plotly.express as px
controls = dbc.FormGroup(
[
html.P('Pick Date', style={
'textAlign': 'center'
}),
dcc.DatePickerRange(
id = "date-picker",
start_date = datetime(2021,1,1),
end_date = datetime.today(),
display_format='MMMM Y, DD'
),
html.Br(),
dbc.Button(
id='submit_button',
n_clicks=0,
children='Submit',
color='primary',
block=True
),
]
)
content_second_row = dbc.Row(
[
dbc.Col(
dcc.Graph(id='graph_2'), md=4
)
]
)
@app.callback(
Output('graph_2', 'figure'),
[Input('date-picker', 'start_date'),
Input('date-picker', 'end_date')],
[State('submit_button', 'n_clicks')])
def update_graph_2(n_clicks, start_date, end_date):
fig = {
'data': [{
'x': dfEconomic[(dfEconomic['Date']>start_date)&(dfEconomic['Date']<end_date)],
'y': dfEconomic["Amount [DKK]"],
'type': 'bar'
}]
}
return fig
I have tried to convert the date values to dateframes, by the use of following code:
for i in range(len(dfEconomic["Date"])):
if isinstance(dfEconomic["Date"][i], str) == True:
dfEconomic["Date"] = datetime.strptime(dfEconomic["Date"][i], "%Y-%m-%d")
But it has not helped the situation. I get the following error message:
TypeError: invalid type comparison
Can anyone help me understand what needs to be changed?
Solution 1:[1]
This might be useful for those who faces this issue while using dash DatePickerRange with a callback function associated with it.
The dash callback function reads the start and end date of the DatePickerRange component as string. So, you will get an error when slicing the pandas dataframe by comparing the date values in a column with the start and end data values in the DatePickerRange.
Follow these steps to ensure that the date type matches and your callback function works as expected:
Ensure that the datatype of the column you are trying to filter is of the type
datetime.date
. You can do so by adding this code -dfEconomic['Date'] = pd.to_datetime(dfEconomic['Date']).dt.date
Then convert the data type of the
start_date
andend_date
coming from DatePickerRange in the callback function -
start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d').date()
end_date = datetime.datetime.strptime(opp_end_date, '%Y-%m-%d').date()
So, the updated callback function should look like this:
import datetime
@app.callback(
Output('graph_2', 'figure'),
[Input('date-picker', 'start_date'),
Input('date-picker', 'end_date')],
[State('submit_button', 'n_clicks')])
def update_graph_2(n_clicks, start_date, end_date):
dfEconomic['Date'] = pd.to_datetime(dfEconomic['Date']).dt.date
start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d').date()
end_date = datetime.datetime.strptime(opp_end_date, '%Y-%m-%d').date()
fig = {
'data': [{
'x': dfEconomic[(dfEconomic['Date']>start_date)&(dfEconomic['Date']<end_date)],
'y': dfEconomic["Amount [DKK]"],
'type': 'bar'
}]
}
return fig
Feel free to adjust the format of your datetime object as per the requirement.
Solution 2:[2]
- simulated dataframe and constructed a dash layout to make your code runnable
- three core issues
- the order of the parameters to callback were wrong. n_clicks is last parameter
- used
pd.to_datetime()
to convert string values todatetime64[ns]
. Created a list that can then used as*args
tobetween()
- need to filter x and y so used a local variable df
import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
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 jupyter_dash import JupyterDash
app = JupyterDash(__name__)
dfEconomic = pd.DataFrame({"Date": pd.date_range("1-jan-2021", "today")}).assign(
**{"Amount [DKK]": lambda d: np.random.uniform(10, 200, len(d))}
)
controls = dbc.FormGroup(
[
html.P("Pick Date", style={"textAlign": "center"}),
dcc.DatePickerRange(
id="date-picker",
start_date=datetime(2021, 1, 1),
end_date=datetime.today(),
display_format="MMMM Y, DD",
),
html.Br(),
dbc.Button(
id="submit_button",
n_clicks=0,
children="Submit",
color="primary",
block=True,
),
]
)
content_second_row = dbc.Row([dbc.Col(dcc.Graph(id="graph_2"), md=4)])
app.layout = html.Div([controls, content_second_row])
@app.callback(
Output("graph_2", "figure"),
[Input("date-picker", "start_date"), Input("date-picker", "end_date")],
[State("submit_button", "n_clicks")],
)
def update_graph_2(start_date, end_date, n_clicks):
df = dfEconomic.loc[dfEconomic["Date"].between(*pd.to_datetime([start_date, end_date]))]
fig = {"data": [{"x": df["Date"], "y": df["Amount [DKK]"], "type": "bar"}]}
return fig
if __name__ == "__main__":
# app.run_server(debug=True)
app.run_server(mode="inline")
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Shivam Solanki |
Solution 2 | Rob Raymond |