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?

The dataframe looks the following

Answer

  • simulated dataframe and constructed a dash layout to make your code runnable
  • three core issues
    1. the order of the parameters to callback were wrong. n_clicks is last parameter
    2. used pd.to_datetime() to convert string values to datetime64[ns]. Created a list that can then used as *args to between()
    3. 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")