Black Lives Matter. Please consider donating to Black Girls Code today.

Slider not working

Hi Guys,

Following is the code for a scatter plot with year-month input in form of slider.

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
import sqlalchemy as sq
from datetime import datetime

engine_prd = sq.create_engine(“connection URL”)
df=pd.read_sql(“select substring(order_created_date,1,4)|| ‘-’ || substring(order_created_date,5,2) as year_month,master_category, article_type,brand,sum(item_revenue_inc_cashback+shipping_charges_shipment+gift_charges_shipment+cod_charges_shipment) as revenue,sum(item_revenue_inc_cashback)/count(distinct order_group_id) as ASP,count(distinct order_group_id) as num_orders, sum(order_quantity) as order_quanitity from fact_core_item where order_created_date>20170101 and store_id=1 and (is_realised=1 or is_shipped=1) group by year_month,master_category,article_type,brand ;”,engine_prd)

year_month=df[‘year_month’].unique()

app=dash.Dash()

app.layout=html.Div([
dcc.Graph(id=‘graph-with-dropdown’),
dcc.Slider(
id=‘year-month-slider’,
min=‘2017-01’,
max=‘2018-02’,
value=‘2018-02’,
step=None,
#marks={i: ‘Label {}’.format(i) for i in df[‘year_month’].unique()},
marks={str(yearm) : str(yearm) for yearm in df[‘year_month’].unique()}

	)
])

@app.callback(
dash.dependencies.Output(‘graph-with-dropdown’, ‘figure’),
[dash.dependencies.Input(‘year-month-slider’, ‘value’)])

def update_figure(selected_year_month):
filtered_df=df[df.year_month==selected_year_month]
traces=[]

for i in filtered_df.master_category.unique():
	df_by_master_category=filtered_df[filtered_df['master_category'] == i]

	traces.append(go.Scatter(
		 x=df_by_master_category['revenue'],
		 y=df_by_master_category['asp'],
		 text=df_by_master_category['brand']+'-'+df_by_master_category['article_type'],
		 mode='markers',
		 opacity=0.3,
		 marker={
		 'size':15,
		 'line': {'width': 0.5, 'color': 'white'}
	 	},
	 	name=i
	 ))
return {
	'data': traces,
    'layout': go.Layout(
        xaxis={'type': 'log', 'title': 'Total Revenue'},
        yaxis={'title': 'Average Selling Price'},
        #margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
        legend={'x': 0, 'y': 1},
        hovermode='closest'
    )

}

if name == ‘main’:
app.run_server()

Following is the df.head() output:

year_month master_category article_type brand revenue asp num_orders order_quanitity
0 2017-01 Accessories Accessory Gift Set Hakashi 9.274500e+02 927.450000 1

The plot’s slider is not working. Will be great if someone can point out the error.

Is selected_year_month definitely the same data type as df.year_month?
According to your ‘marks’ in your slider selected_year_month will be a sting. The values df.year_month may be integers?

Hey Mike

Year-month is a string datatype. To stay safe I also used:
df[‘year_month’]=df[‘year_month’].astype(str) initially. Yet the slider isn’t working.

What do you mean by insn’t working? Are there any errors in the console?

Attached is the screenshot. First, the labels on slider don’t appear. Secondly, chart turns blank if clicked anywhere on slider.

So I think the problem is the way you are defining the Slider parameters compared to what the component expects. The keys in the marks dictionary seem to want to be integers (or stringified ints) so that the min and max values can be treated as a range. You can then use the State of the marks to get the date label eg:

app.layout=html.Div([
    dcc.Graph(id=‘graph-with-dropdown’),
    dcc.Slider(
        id=‘year-month-slider’,
        min=0,
        max=len(df[‘year_month’].unique()), # max value is the number of unique values
        value=0, # set the value to 0
        marks={i : str(yearm) for i, yearm in enumerate(df[‘year_month’].unique())} # enumerate the dates
	)
])

@app.callback(
    dash.dependencies.Output(‘graph-with-dropdown’, ‘figure’),
    [dash.dependencies.Input(‘year-month-slider’, ‘value’)],
    [dash.dependencies.State(‘year-month-slider’, ‘marks’)]) # Add the marks as a State
def update_figure(selected_year_month_key, marks):
    selected_year_month = marks[str(selected_year_month_key)] # use the selected marker to get date
    filtered_df=df[df.year_month==selected_year_month]
    traces=[]

    for i in filtered_df.master_category.unique():
        df_by_master_category=filtered_df[filtered_df['master_category'] == i]
        traces.append(go.Scatter(
            x=df_by_master_category['revenue'],
            y=df_by_master_category['asp'],
            text=df_by_master_category['brand']+'-'+df_by_master_category['article_type'],
            mode='markers',
            opacity=0.3,
            marker={
            'size':15,
            'line': {'width': 0.5, 'color': 'white'}
            },
            name=i
	 ))
    return {
            'data': traces,
            'layout': go.Layout(
            xaxis={'type': 'log', 'title': 'Total Revenue'},
            yaxis={'title': 'Average Selling Price'},
            legend={'x': 0, 'y': 1},
            hovermode='closest'
    )
}

That worked! Thanks so much for your help. I just have some queries to understand it better:

  1. I don’t know much about ‘State’ and its usage. Is there a documentation regarding that?
  2. In selected_year_month = marks[str(selected_year_month_key)], why is str required over the selected_year_month_key. Marks dictionary has ‘i’ (an integer) as key if I am correct.

Thanks again for your help.

No problem!

  1. See here: https://plot.ly/dash/state

  2. This is probably a bug in the Slider component that assumes the dictionary keys for marks are of type string (JSON doesn’t accept integer keys I believe) and doesn’t attempt to convert them. Is this the case @chriddyp?

That sounds right. In JavaScript and JSON, dictionary keys are strings. I logged the issue here: https://github.com/plotly/dash-core-components/issues/163