Context for CategoricalAxis levels

Hello,

I want to implement a context for CategoricalAxis like for DatetimeTickFormatter for DatetimeAxis but I can’t find where to start (“entry point”).

I want to change the view (tick frequency or/and label format) for both major-level and group(subgroup)-level depending on the zoom (axis scale).

It looks like CustomJSTickFormatter needs to be used (custom_js_tick_formatter — Bokeh 3.3.2 Documentation).

For example this feature will be useful for the Categorical Axis with DateTime-like upper (group) axis level. See Bar charts — Bokeh 3.3.2 Documentation for example: year-axis (group-level, DateTime-like) should be changed on zoom (rescaling) while fruits-axis (major-level) doesn’t need to be changed.

(major, group and subgroup in terms of bokeh.models.CategoricalAxis attributes).

Thanks in advance for any advice.

@dinya it’s not clear from your post—are you wanting to implement something for a plot you are making with Bokeh, or are you wanting to implement a new feature in Bokeh itself? CustomJS features could be relevant for the former, but not the latter. CustomJS models not used anwhere in the internal implementation of Bokeh, they are user-facing only.

It’s also not clear what exactly you want to accomplish from the description. Do you have an image or a link to something that shows what you want to be able to do?

Lastly, I have to be frank and state that the code for multi-level categorical ranges and axes is very complicated. I’m not exaggerating when I say it’s in the top-five most complex corners of BokehJS. There are, at least, lots of tests to cover this area, but I want to be clear that most any work in this area will not be trivial.

@Bryan Thanks for the feedback.

it’s not clear from your post—are you wanting to implement something for a plot you are making with Bokeh, or are you wanting to implement a new feature in Bokeh itself?

I’m solving my current task, so it’s more about customizing my plot.

Although, perhaps this feature would be useful for other users, so it would be cool to have it in the library’s functionality. Is this discussion is subject for sending a request for a new feature to Issues · bokeh/bokeh · GitHub?

It’s also not clear what exactly you want to accomplish from the description. Do you have an image or a link to something that shows what you want to be able to do?

I’m sorry that I didn’t provide an illustrative example right away.

See the following figures. date axis on the left subplot on the figure is group-level. Because of a lot of boxes groups the tick labels are overlapped (compare axis labels at original and zoomed figures).

Original figure Zoomed figure

The Jupyter sheet with plot procedure is here Attachment for https://discourse.bokeh.org/t/context-for-categoricalaxis-levels/11132 · GitHub. I use Holoviews Boxwhisker, however Holoviews itself uses Bokeh as a plotting backend, so the question can be extended to any Bokeh entity uses CategoricalAxis. And I use dataset based on bokeh.sampledata.autompg.

I want to have the same behavior on rescaling (zooming/unzooming) along the date axis as for DatetimeAxis like Styling plot elements — Bokeh 3.3.2 Documentation — the axis view (labels, ticks) is adapted to current rendered data. For example, only years are displayed on the “macro” scale, months on the “middle” scale, and so on with “normal” ticks frequency (the overlapping problem). The ticks label format (and their frequency) should be configurable as is the case with DatatimeAxis.


Originally my plot (library) was implemented with Matplotlib (Seaborn).

The output is static images so date axis generation (overlap calc, ticklabel format) is done before image will show. And the whole image replot (with new axis calc) is need for the new scale.

(I haven’t tried to implement interactive axis reformat on rescale. Perhaps it’s complicated task too.)

However, despite the excellent quality of the generated images by Matplotlib, the rendering speed and the interactivity (e.g., web application) are low. (It’s still a great tool, but for other goals.)

Therefore, I am currently working on adding Bokeh (Holoviews) as a faster and more interactive backend (as more suitable tool). And the axis reformat on rescale in interactive mode will be a pretty useful feature.

It seems like you don’t actually want a categorical axis. By definitition, categorical factors are arbitrary identifiers (strings). They don’t have any notion of scale or even order. In particular, this arbitrary nature is why categorical axes just display all the categories (there is no possible “right” way to reduce the number of ticks that always makes sense for every user and every use case).

It seems like you want a datetime axis. Datetime axes already do all the thing you are looking for: contexts, different formats at different scales, picking a “nice” number of ticks based on scale. Have you considered re-working your plot to use a datetime axis?

Otherwise, I don’t think what you want to accomlplish will be simple or easy with a categorigical axis.

I would like to use DateTimeAxis, but I have no idea how to organize the grouping: so that in general case there are several grouped “points” per tick (for example, boxes standing next to each other). That’s why I started using the CategoricalAxis, where a datetime column is used for grouping.

Do you have any ideas?

Speculating purely based on the image above, I think you’d have to force a “grouping” by using a visual dodge, similar to this example in the docs:

https://docs.bokeh.org/en/latest/docs/user_guide/basic/bars.html#visual-offset

1 Like