I created a non-linear slider, but the marks are not evenly distributed on the slider. They are somehow sitting on each other. If I use linear values, the slider is working fine. But my values are in a log scale.
There is an example of a non-linear slider in the docs here, but there is a small bug in the example (the marks don’t appear). Below is an updated version so you can see the scale on the slider:
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import dash
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
# Use the following function when accessing the value of 'my-slider'
# in callbacks to transform the output value to logarithmic
def transform_value(value):
return 10 ** value
app.layout = html.Div([
dcc.Slider(
id='slider-updatemode',
marks={i: {'label': '{}'.format(10 ** i)} for i in range(4)},
min=0,
max=3,
value=2,
step=0.01,
updatemode='drag'
),
html.Div(id='updatemode-output-container', style={'margin-top': 20})
])
@app.callback(Output('updatemode-output-container', 'children'),
Input('slider-updatemode', 'value'))
def display_value(value):
return 'Linear Value: {} | \
Log Value: {:0.2f}'.format(value, transform_value(value))
if __name__ == '__main__':
app.run_server(debug=True)
As you can see in the code, to archive an evenly distributed spacing between the marks, my values are the numbers from 1 to 6. But I need the numbers 0.001 to 0.5 like the marks as input values in callbacks.
Hi @cody
If you look at the example, the log value is calculated in the callback:
# Use the following function when accessing the value of 'my-slider'
# in callbacks to transform the output value to logarithmic
def transform_value(value):
return 10 ** value
In your case, to get the range you are looking for, you can adjust the min and max values of the slider. For example, to get a scale from 0.001 to 1, you could use a min=-3 and max=0
Hi @AnnMarieW
I understand. But what do I do when I want to have exactly these values only: 0.001, 0.005, 0.01, 0.05, 0.1 and 0.5? Nothing in between?
Am I even supposed to use a slider for that? What do you think are better selection options for such a case? Those numbers are parameters for a function. Each of those parameters will have a different affect on a graph shown as an output.
If you really want a slider, you can set the steps so you only get the numbers you want, but for this use-case, a Dropdown or even RadioItems might work better for you.
So, I found a solution to my problem. Huge thanks to @AnnMarieW for her input. She suggested to use a function to transform the values. I wrote a function that uses a dictionary to map the slider input value to whatever value I need, but still maintaining an even spacing between the marks on the slider. Keep in mind, when the values of the slider (marks) are not linear scale (e.g. 1,3,5,7,9,…), but rather log scale or non-linear scale (e.g. 1,2,6,14,30), the slider will have the marks sitting on each other. That is because the steps are not going up by a constant factor like step=1. This problem (see OP) renders the slider pretty much useless.
dcc.Slider(
id='non_linear_scale_slider',
min=1,
max=6,
step=None,
marks={
1: '0.001',
2: '0.005',
3: '0.01',
4: '0.05',
5: '0.1',
6: '0.5'
},
value=4
)
# Use in a callback to transform input value of slider to arbitrary value
def transform_value(slider_value):
int_to_scale = dict([
(1, 0.001),
(2, 0.005),
(3, 0.01),
(4, 0.05),
(5, 0.1),
(6, 0.5)
])
return int_to_scale[slider_value]