dash-core-components icon indicating copy to clipboard operation
dash-core-components copied to clipboard

Slider labels not showing when keys are float

Open cgranier opened this issue 7 years ago • 12 comments

When I create my slider marks like this:

marks={ 10.0: '10.00%', 25.0: '25.00%', 50.0: '50.00%', 75.0: '75.00%', 100.0: '100.00%' }

the slider labels will not show up. I just get a slider with marks but no labels. The marks still work as expected and will filter the chart according to the keys.

image

Using this:

marks={ 10: '10.00%', 25: '25.00%', 50: '50.00%', 75: '75.00%', 100: '100.00%' }

results in a slider with the proper labels underneath. This slider also works as expected (because my values all have .0 as the decimal value, I suppose).

image

cgranier avatar Feb 10 '18 02:02 cgranier

I'm also having this issue. When the keys are not divisible by 1, it works for the keys to be floats, but when the keys are divisible by 1, marks only appear if the keys used are ints. Because I'm dynamically generating the marks, I'm having to use: marks={int(i) if i % 1 == 0 else i: '{}'.format(i) for i in points_to_mark}

peterscherpelz avatar Apr 11 '18 20:04 peterscherpelz

When I use this slider the labels for the min and max values are missing:

dcc.Slider(
    id='opacity-slider',
    min=0.0,
    max=1.0,
    value=0.5,
    step=None,
    marks={opacity: f'{opacity:.1f}' for opacity in [0.0, 0.4, 0.5, 0.6, 1.0]}
)

Seems to be a related issue.

dimiboi avatar Mar 23 '19 14:03 dimiboi

I am observing the same thing as @cgranier. Here are two sliders, built with the same python code

image

At first I was suspecting something wrong happening if marks are placed that are unreachable (not in the form min + x * step) but looking into the numbers that does not seem to be the reason.

Here is the code building the range slider

    slider_element = dcc.RangeSlider(
        id=dict(type="slider", role="input", data=id),
        min=data_range.min,
        max=data_range.max,
        value=[data_range.min, data_range.max],
        step=step,
        marks=mark_labels,
        allowCross=False,
        tooltip=dict(always_visible=True,placement="left") # tested without this line, same problem
    )
  • the first one (Height), that works, was given the following params:
min=1.63,
max=1.89,
step=0.01,
marks={1.63: {'label': '1.63'},
 1.69: {'label': '1.69'},
 1.7599999999999998: {'label': '1.76'},
 1.8199999999999998: {'label': '1.82'},
 1.89: {'label': '1.89'}}
  • the second one (Weight) does not work, and got:
min=61.0,
max=79.0,
step=0.1,
marks={61.0: {'label': '61.0'},
 67.0: {'label': '67.0'},
 73.0: {'label': '73.0'},
 79.0: {'label': '79.0'},
 85.0: {'label': '85.0'}}

Exploring the html code with Firefox dev tools, I noticed that in (1), the 5 marks are contained in a <div class="rc-slider-marks">.
The same div exists for the weight slider, but is empty.

I hope those information can help anyone looking into this to pinpoint the root cause. In the meantime, thanks for dash, it is bringing a real value in our company :)


Proposed work-around I wrote the following work-around, that works in my case:

    mark_values = np.linspace(min_value, max_value, 5) # whatever computes the position of the marks
    mark_labels = {}
    for mark_val in mark_values:
        # work-around bug reported in https://github.com/plotly/dash-core-components/issues/159
        # if mark keys happen to fall on integers, cast them to int
        if abs(mark_val-round(mark_val)) < 1e-3: # close enough to an int for my use case
            mark_val = int(mark_val)
        mark_labels[mark_val] = {"label": str(round(mark_val, round_decimal))})

    slider = dcc.RangeSlider(
        marks=mark_labels,
        ...)

Arpafaucon avatar Jan 15 '21 09:01 Arpafaucon

I have run into the same issue three years later, is there a fix or workaround?

hughjward avatar Jul 16 '21 15:07 hughjward

I have run into the same issue three years later, is there a fix or workaround?

I'm also seeing the same buggy behavior, using Python 3.8.5 and plotly 5.1.0.

@Arpafaucon described a workaround above, and you can see another one in a related plotly forum thread (unlike Arpafaucon's suggestion, this one only works if you don't have any 'actual decimal values' like say 57.2 in your data).

datalowe avatar Aug 10 '21 08:08 datalowe

@Arpafaucon answer seems to be the best one. When I came across this issue a few years ago, I went with rescaling my values to become integers, which works but introduces a new factor that can cause issues with processing.

the-rccg avatar Aug 10 '21 09:08 the-rccg

@Arpafaucon workaround is good but seriously how is this still a bug? Just had problems with it today, this thread is 4 and a half years old

crabbixOCE avatar Sep 23 '22 02:09 crabbixOCE

My solution is to add a small Epsilon value to floats, like marks = {0.0 + eps: {'label': 'first'}}

mcstarioni avatar Dec 16 '22 15:12 mcstarioni

Same problem... Also added an epsilon to the floats but needed to take care to make it negative for the mark on the high end so that it doesn't disappear. e.g. slider goes from 0 to 1 and I have marks every 0.1. then adding 0.00001 will make the last mark at 1.00001 which means it wont show, so I subtract 0.00001 from that one. Anyway, the developers should really fix this one

hamdav avatar Sep 05 '23 10:09 hamdav

Popping in to confirm that I'm also still getting this bug :)

carschandler avatar Oct 09 '23 17:10 carschandler

The "small epsi" solution by @mcstarioni worked for me.

I just note that small-epsi values do overwrite themselves: my use case is that I have a b c where b can be equal to a or c, so:

marks = { a+epsi: ..., b+epsi: ..., b-epsi: ..., c-epsi: ...}

(where ... is like {'label', str(a), 'style': {'color': '#f50'}}") did now work when b==c because c's style overwrites b's.

However this worked:

marks = { a+epsi: ..., b+epsi: ..., c-epsi: ..., b-epsi: ... }

danieleongari avatar Oct 25 '23 09:10 danieleongari