plotly.js icon indicating copy to clipboard operation
plotly.js copied to clipboard

ticklabelindex property does not work for dticks spanning multiple periods

Open stephprobst opened this issue 6 months ago • 4 comments

Problem description:

The current implementation of the ticklabelindex property does not work for dticks that span multiple periods when no minor ticks are present.

Please consider the following example (https://codepen.io/stephprobst/pen/MYYMjmr):

Image

Due to setting '"ticklabelindex": -1', the label to the left of the major tick gets drawn (2023 / 2025) instead of the label to right of the major tick (2024 / 2026).

This is correct and works as it should. Now let's consider another example, where the minor ticks are not shown (https://codepen.io/stephprobst/pen/RNNzROd):

Image

Even though '"ticklabelindex": -1' is set as before, the label to the right of the major tick (2024 / 2026) gets now drawn. This causes some issues for us, as we cannot rely on the ticklabelindex to always work as expected.

There is yet another scenario, where '"ticklabelindex": -1' does not work exactly as expected. Please consider this third codepen (https://codepen.io/stephprobst/pen/LEEKRBK):

Image

In this example, instead of minor ticks we use "ticklabelstep": 2 for a similar layout. I would now have expected the '"ticklabelindex": -1' property to have the same effect as before with the minor ticks: Drawing the label to the left of the major tick (2023 / 2025). But this is not the case.

Why this is relevant:

The behaviour as described above prevents us from creating the following automation:

  • Makes sure the last visible tick is a major tick
  • Makes sure the label for the last data point is drawn

For both scenarios we set the tick0 property, but depending on the presence of minor ticks or the distance between the ticks the label behaves differently with `"ticklabelindex": -1' in place (which is our default).

Expected behavior:

The "ticklabelindex": -1 property should behave consistent across all the use cases listed above. In all examples, the labels 2023 and 2025 should be shown.

stephprobst avatar May 20 '25 11:05 stephprobst

It's not straightforward how this issue should be solved. Currently, ticklabelindex determines which minor tick's label should be shown. So when no minor ticks exist (or when their ticklen is 0), the property has no effect. The expected behavior here is that "ticklabelindex": -1 always draws the label to the left of the major tick. Some alternative solutions for this would be

  1. Make "ticklabelindex": -1 a special case in which extra logic is implemented to draw the label left of the tick.
  2. Change plotly behavior so that labels for minor ticks with "ticklen": 0 are still generated. Then one can make ticklabelindex work with invisible minor ticks.
  3. Add a new property for period axes to specify if the label left or right of the tick should be drawn.

Option 1. is not so nice because it adds a special case. And the index part of the name doesn't make a lot of sense for that special case. Option 2. requires a little bit of a hack on user side to achieve the desired behavior. Option 3. seems to be what we want semantically, but might be a little bit confusing because the behavior of ticklabelindex would then depend on how this new property is set.

@stephprobst @emilykl @gvwilson What do you think about this? Is there another option 4.?

my-tien avatar May 26 '25 10:05 my-tien

@emilykl @archmoj thoughts on the best way forward?

gvwilson avatar Jun 03 '25 12:06 gvwilson

@stephprobst @my-tien I spent a few hours yesterday looking at this one. @archmoj @alexcjohnson please correct me if I'm making any false assumptions.

I think the behavior definition for ticklabelindex is pretty clear, and we should stick to it: "Instead of drawing the major tick label, draw the label for the minor tick that is n positions away from the major tick."

I think that the root issue in both of ths, if the minor ticks are not visible (either because ax.minor is not defined, or because some other combination of values causes us to decide not to draw the minor ticks), we never even calculate the minor tick positions; therefore there are no values to choose from when trying to pick a value to use for ticklabelindex.

My thought:

  • If ax.ticklabelindex is passed, regardless of whether any values are provided for ax.minor, we should calculate positions for all minor ticks (using default values if necessary), and then use those values to select the correct minor tick label to display, according to ax.ticklabelindex.

    • I'm not sure yet how complex this will be in practice
  • I do also feel that setting ticklabelindex without setting a dtick for the minor ticks is not a great idea, since AFAIK we don't guarantee any particular default spacing for minor ticks, so you don't necessarily know exactly what minor tick label you'll get. Nonetheless, there's no reason we can't support it, while still recommending that minor.dtick be defined for predictable behavior.

emilykl avatar Jun 10 '25 15:06 emilykl

Hi Emily, that's an interesting idea. I just wonder if the feature isn't too weird in the sense that you probably never want to create a chart like this where the major tick interval is 3 years and minor ticks are invisible but have an interval of 1 year and ticklabelindex is 1:

|                         |                         |
            2025                      2028

This is strange because each label individually looks as if it labels the whole span between the two ticks while in reality it just denotes an invisible interval in between.

Yet another idea: Introduce special keywords left and right as values for ticklabelindex. right would be identical to ticklabelindex 0 and left would just draw the label on the left of the major tick.

my-tien avatar Jun 11 '25 08:06 my-tien

@emilykl , @gvwilson - Any progress on this issue? Anything else you'd need from our side to move this forward? I think the proposal by My-Tien to implement left and right as special keywords seems good to me? This should be fully backwards compatible, as it only introduces new options and the implementation effort should also stay reasonable? Thanks!

stephprobst avatar Sep 04 '25 11:09 stephprobst

hi @stephprobst - my apologies for the radio silence - Plotly Studio and Plotly Cloud are launching today, so all of our efforts have been focused on that.

gvwilson avatar Sep 09 '25 14:09 gvwilson

Hi @gvwilson, hi @emilykl, congratulations on the launch. We'll make sure to check out the new tools. And thanks for giving this issue priority.

stephprobst avatar Sep 22 '25 12:09 stephprobst