Having Trouble Formatting Marks on RangeSlider Dash

Hello,

I am working on creating a map with Dash in Python and I am having some trouble with a time slider.

Originally, I had the day as the inputs for the time slider, but whenever there was a gap with the date from Jan 1st to Jan 3rd or just moving from one month to another (eg: Jan 31st to Feb 1st), there was a gap on the time slider.

I wanted to have evenly spaced out marks on my time slider. So, I converted the dates to just numbers. Day 1, 2, 3, and so on regardless if they were consecutive days. This seemed to fix the problem of the gaps on the time slider, but now I’m not sure how to properly label the marks without explicitly labeling them for each date.

Here is a reproducible example:

import pandas as pd
import numpy as np
    
import plotly.graph_objects as go
import plotly.express as px
    
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
    
    
df = [[-77.070033, 38.955367, 20200101],
          [-74.070033, 38.955367, 20200101],
          [-77.070033, 38.755367, 20200102],
          [-77.070033, 38.655367, 20200102],
          [-77.070033, 38.555367, 20200103],
          [-77.070033, 38.455367, 20200104],
          [-77.070033, 38.955367, 20200105],
          [-77.070033, 38.955367, 20200106],
          [-77.040033, 38.955367, 20200108],
          [-77.090033, 38.155367, 20200115],
          [-77.050033, 38.055367, 20200116],
          [-77.070033, 38.655367, 20200124],
          [-77.070033, 39.955367, 20200124],
          [-77.070033, 40.955367, 20200125],
          [-76.070033, 38.955367, 20200131],
          [-74.070033, 38.955367, 20200201]]
    
df=pd.DataFrame(df,columns=['X','Y','Date']) 
df['DateCount'] = df['Date'].factorize()[0] + 1
    
    
fig = go.Figure()
    
fig = px.scatter_mapbox(df, lat="Y", lon="X", hover_data={"Date":True,
                                                              "X":False,
                                                              "Y":False},
                             zoom=10, height=600)
    
fig.update_layout(mapbox_style="stamen-terrain",autosize=True,hovermode='closest')
    
    
    
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets) 
app.layout = html.Div([
      html.Div([
            html.H3('Example Map', style={'text-align': 'center'})
      ], className="row"),
    
      html.Div([
         dcc.Graph(figure=fig, id='map')
      ], className="row"),

      html.Div([
            dcc.Slider(id='slider',
                       min=df['DateCount'].min(),
                       max=df['DateCount'].max(),
                       value=[df['DateCount'].max()],
                       marks={str(date): str(date) for date in df['DateCount'].unique()},
                       step=None)

      ], className="row")
    
    
])

    
@app.callback(
     Output('map','figure'),
     Input('slider','value'))

def update_figure(selected_date):
        filtered_df = df[(df.DateCount <= selected_date)]

    
    
        fig = px.scatter_mapbox(filtered_df, lat="Y", lon="X", zoom=10, height=550,
                            hover_data={"Date":True,
                                        "X":False,
                                        "Y":False}
                        )

        fig.update_layout(mapbox_style="stamen-terrain")


        fig.update_geos(fitbounds="locations")
        fig['layout']['uirevision'] = 2


        return fig



app.run_server(host='0.0.0.0',port='8050') 

Can someone help me figure out how I can use the dates to label the consecutive numbers in the time slider? Thank you!

Hi @plotme1
Here is one way to do this:

Change:

df['DateCount'] = df['Date'].factorize()[0] + 1

to:

df['DateCount'] = df['Date'].factorize()[0] 

Then change the slider marks to:

marks={each : str(date) for each, date in enumerate(df['Date'].unique())},

Also, remove the extra [ ] from the value so it looks like:

value=df['DateCount'].max(),

I hope this helps!

1 Like

Thanks @AnnMarieW ! That was exactly what I was looking for! However, the labels are now overlapping, so I’m trying to add some styling to the marks argument to try to rotate them so they can all be read. But, I keep getting invalid syntax errors.

Where should I place the following in the marks argument?
“style”: {“transform”: “rotate(45deg)”}

Try this:

marks={each : {"label": str(date), "style": {"transform": "rotate(45deg)"}} for each, date in enumerate(df['Date'].unique())},
1 Like

Thanks! It’s perfect!

1 Like