saladi
saladi

Reputation: 3263

Swap axes after plot object created in bokeh

I need to swap the x and y axes of a plot after the plot object has been created with Bokeh. I've tried to do this as follows but get the following javascript error:

Javascript Error: Cannot read property 'length' of undefined

I think this might be possible because of this bokeh issue with related PR and gist.

I'm wondering what I'm missing (or not understanding) here to get this to work.

import bokeh.plotting
import bokeh.io

def swap_axes(plot):
    old_x_axis, old_y_axis = plot.below[0], plot.left[0]
    old_x_range, old_y_range = plot.x_range, plot.y_range
    old_x_scale, old_y_scale = plot.x_scale, plot.y_scale

    plot.below = []
    plot.left = []
    plot.add_layout(old_y_axis, 'below')
    plot.add_layout(old_x_axis, 'left')

    plot.x_range, plot.y_range = old_y_range, old_x_range
    plot.x_scale, plot.y_scale = old_y_scale, old_x_scale
    plot.center = plot.center[::-1]

    return plot


fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
counts = [5, 3, 4, 2, 4, 6]

p = bokeh.plotting.figure(x_range=fruits, plot_height=250, title="Fruit Counts",
                          toolbar_location=None, tools="")
p.vbar(x=fruits, top=counts, width=0.9)

bokeh.io.show(p)
bokeh.io.show(swap_axes(p))

Working vs error output

Upvotes: 0

Views: 388

Answers (1)

bigreddot
bigreddot

Reputation: 34628

It's unclear why you would ever need to update a plot a plot in place in this manner outside a Bokeh server application, which actually keeps live objects in sync across the Python/JS runtime. In standalone HTML output there is literally no important way in which one plot being used to two separate file would be distinguishable from two plots being used to generate two separate files.

Regardless, this particular kind of re-arranging is going to be especially troublesome with Bokeh, as there are very many pieces that would need to be shuffled correctly. Besides what you have above, the tickers for the axes also drive the grids, those would need to be fixed up. This line: plot.center = plot.center[::-1] does nothing of use (it does not change how the grids are configured, merely the order they are drawn). There are probably other things that need to be swapped as well.

It's a non-trivial task and basically no one has asked for it in ~6 years so we have not invested any of the very finite project resources into making it easy. My advice, as one of the lead core developers, is that you should make a function that can return two versions of the plot, based on a flag parameter, and show the two separate plots:

show(make_plot(swapped=False))
show(make_plot(swapped=True))

Also:

but just get a javascript error.

For future reference, if there is an error message, it should always, always, always be included with the question.

Upvotes: 2

Related Questions