Get underlying Bokeh figure object back from hvplot

Given an hvplot.pandas figure, is it possible to retrieve the underlying Bokeh figure object? There are some changes I’m trying to make that I know how to do in Bokeh, but I cannot reach via hvplot.pandas.


You can access through hooks.

FAQ — HoloViews 1.14.5 documentation (probably should add section headings to the FAQ for easily pastable links)

Q: Can I export and customize a bokeh or matplotlib figure directly?

A: Sometimes it is useful to customize a plot further using the underlying plotting API used to render it. The hv.render method returns the rendered representation of a holoviews object as bokeh or matplotlib figure:

# Using bokeh
p = hv.render(obj, backend='bokeh')

# Using matplotlib
fig = hv.render(obj, backend='matplotlib')
Note that the backend is optional and will default to the currently activated backend (i.e. hv.Store.current_backend).

If the main reason you want access to the object is to somehow customize it before it is plotted, instead consider that it is possible to write so called hooks:

def hook(plot, element):
  # The bokeh/matplotlib figure

      # A dictionary of handles on plot subobjects, e.g. in matplotlib
      # artist, axis, legend and in bokeh x_range, y_range, glyph, cds etc.

hv.Curve(df, 'x_col', 'y_col').opts(hooks=[hook])
These hooks can modify the backend specific representation, e.g. the matplotlib figure, before it is displayed, allowing arbitrary customizations to be applied which are not implemented or exposed by HoloViews itself.

Q: What if I need to do more complex customization supported by the backend but not exposed in HoloViews?

A: If you need to, you can easily access the underlying Bokeh or Matplotlib figure and then use Bokeh or Matplotlib’s API directly on that object. For instance, if you want to force Bokeh to use a fixed list of tick labels for a HoloViews object h, you can grab the corresponding Bokeh figure b, edit it to your heart’s content as a Bokeh figure, and then show it as for any other Bokeh figure:

import holoviews as hv
h = hv.Curve([1,2,7], 'x_col', 'y_col')

from import show
from bokeh.models.tickers import FixedTicker

b = hv.render(h)
b.axis[0].ticker = FixedTicker(ticks=list(range(0, 10)))
Once you debug a modification like this manually as above, you’ll probably want to set it up to apply automatically whenever a Bokeh plot is generated for that HoloViews object:

import holoviews as hv
from bokeh.models.tickers import FixedTicker

def update_axis(plot, element):
    b = plot.state
    b.axis[0].ticker = FixedTicker(ticks=list(range(0, 10)))

h = hv.Curve([1,2,7], 'x_col', 'y_col')
h = h.opts(hooks=[update_axis])
Here, you’ve wrapped your Bokeh-API calls into a function, then supplied that to HoloViews so that it can be run automatically whenever object h is viewed.

Using hooks makes sense if you have some interactive/dynamic object where you’re trying to modify some options which are not exposed in hvPlot/HoloViews during rendering. However if all you want is a Bokeh figure for a static plot the simplest approach is to use the hv.render function:

import holoviews as hv