Search code examples
pythonsliderplotlyplotly-dashgeo

Python Dash - Format Marks on Time Sliders


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!


Solution

  • I think this might work:

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