plotly / dash

Data Apps & Dashboards for Python. No JavaScript Required.

Home Page:https://plotly.com/dash

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Feature Request] Add date support for dcc.Slider/dcc.RangeSlider

celia-lm opened this issue · comments

Describe the solution you'd like

Ideally, something like:

import datetime
from dateutil.relativedelta import relativedelta
# ...
dcc.RangeSlider(
        type='date',
        min=datetime.datetime(2020, 5, 20), 
        max=datetime.datetime(2023, 12, 20), 
        step=relativedelta(months=+6),
        value=[datetime.datetime(2022,10,20), datetime.datetime(2023,5,20)]
)

Less ideally, but understandable since dates are not json serializable (I think?):

dcc.RangeSlider(
        type='date',
        dateformat='%Y-%m-%d',
        min='2020-05-20', # str
        max='2023-12-20',
        step='0-6-0', # 6 months in string format
        # this string information would be transformed to do the calculations in the background with something like
        value=['2022-10-20', '2023-5-20']
)

Describe alternatives you've considered

from dash import Dash, html, dcc, dash_table, Input, State, Output, callback
import plotly.express as px
from dateutil.relativedelta import relativedelta
import pandas as pd
from datetime import datetime

app = Dash(__name__)

df = px.data.stocks(datetimes=True)
all_dates = df["date"]
# transform dates to string in the month/year format
all_dates_my = all_dates.apply(lambda x: x.strftime("%m/%Y")).unique()

app.layout = html.Div([
    # slider for months
    dcc.RangeSlider(
        min=0, 
        max=len(all_dates_my)-1, 
        value=[2,4],
        step=1,
        marks={
            i:{'label': all_dates_my[i]} for i in range(len(all_dates_my))
        },
        id='date-slider-01'),
    # slider for weeks
    html.Div(id='out')
])

@callback(
    Output('out', 'children'),
    Input('date-slider-01', 'value'),
    State('date-slider-01', 'marks')
)
def slider_value(val, marks):
    selected_dates_str = [marks[str(v)]['label'] for v in val]
    # selected_dates = [datetime.strptime(marks[str(v)]['label'], format="%m/%Y")  for v in val]
    filtered_df = df.query(f"date >= '{selected_dates_str[0]}' and date < '{selected_dates_str[1]}'")
    # convert the selected dates into datetime format
    selected_dates = [datetime.strptime(v, "%m/%Y")  for v in selected_dates_str]
    print(selected_dates)

    return [
        html.Div(f"the selected range is from {selected_dates_str[0]} to {selected_dates_str[1]}"),
        dash_table.DataTable(filtered_df.to_dict('records'), [{"name": i, "id": i} for i in filtered_df.columns])
    ]

if __name__ == '__main__':
    app.run(debug=True)

Additional context
Example case where this would be useful instead of using DatePicker:

The datepicker range can only move on a monthly basis and the calendar is redundant. My purpose is to specify the learning period for a machine learning model, and there is no need for calendar (day of the week) information; the key is to choose a range of 24 months.