☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

Nested bar chart truncate long labels

Community Support
blockhart
blockhart

I want to make a nested bar chart that works for arbitrary data, and I want to truncate long labels. I don’t want to truncate the labels before creating the plot since this can introduce ambiguity and I want to show the full label in the tooltip. In this example:

from bokeh.io import show
from bokeh.models import ColumnDataSource, FactorRange
from bokeh.plotting import figure

fruits = ['Apples oranges bananas grapefruit', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
years = ['2015', '2016', '2017']

data = {'fruits' : fruits,
        '2015'   : [2, 1, 4, 3, 2, 4],
        '2016'   : [5, 3, 3, 2, 4, 6],
        '2017'   : [3, 2, 4, 4, 5, 3]}

# this creates [ ("Apples", "2015"), ("Apples", "2016"), ("Apples", "2017"), ("Pears", "2015), ... ]
x = [ (fruit, year) for fruit in fruits for year in years ]
counts = sum(zip(data['2015'], data['2016'], data['2017']), ()) # like an hstack

source = ColumnDataSource(data=dict(x=x, counts=counts))

p = figure(x_range=FactorRange(*x), plot_height=250, title="Fruit Counts by Year",
           toolbar_location=None, tools="")

p.vbar(x='x', top='counts', width=0.9, source=source)

p.y_range.start = 0
p.x_range.range_padding = 0.1
p.xaxis.major_label_orientation = 1
p.xgrid.grid_line_color = None

show(p)

Screen Shot 2020-08-30 at 1.19.32 PM

I want to truncate the “fruit” labels to show the first k characters of the label and then "...". E.g., for the label ’Apples oranges bananas grapefruit' with k=10, the new label will be Apples ora...:

Screen Shot 2020-08-30 at 1.19.54 PM

I have tried using p.xaxis.major_label_overrides and

        p.xaxis.formatter = FuncTickFormatter(
            code="""
            if (tick.length > 10) return tick.substring(0, 10) + '...';
            else return tick;
        """
        )

but these apply to the “year” labels not to the “fruit” labels. Is there any way to get my desired result?

Thanks

⌁   Link to post
p-himik
p-himik

Judging by the code, I don’t think it’s possible to format those labels:

    const ticks = this.model.ticker.get_ticks(start, end, range, loc, {})

    [...]

    } else if (range.levels == 2) {
      const major = (ticks.major as L2Factor[]).map((x) => x[1])
      const labels = this.model.formatter.doFormat(major, this)
      info.push([labels, coords.major, this.model.major_label_orientation, this.visuals.major_label_text])
      info.push([ticks.tops as string[], coords.tops, this.model.group_label_orientation, this.visuals.group_text])

Notice how labels go through formatter.doFormat but ticks are just received straight from the ticker.

With that being said, a workaround is to just shorten the labels in the data. But of course that would require having such labels that don’t conflict with each other when shortened.

Please feel free to create a feature request on GitHub.

⌁   Link to post
p-himik
p-himik

No idea. I’m temporarily away from Bokeh development.

blockhart mentioned a plan to create a feature request on GitHub - you can try searching for it and asking there. And if the feature request doesn’t exist, you can always create it yourself.

⌁   Link to post

End of archived discussion · Replies are disabled