How hvPlot Supports Multiple Plotting Backends#

hvPlot can draw plots with three plotting libraries, called plotting extensions or backends: Bokeh (the default, interactive), Matplotlib (static) and Plotly (interactive). This page explains how this works and why styling options differ from one backend to another. See Supported plotting extensions for how well each one is supported.

hvPlot builds HoloViews objects#

A call like df.hvplot.line() doesn’t draw anything by itself. It returns a HoloViews object, such as a Curve, that holds the data and the plot options. The figure is drawn only when the object is displayed, saved or rendered, and HoloViews then hands the drawing over to the active plotting extension.

Two functions control the extensions:

  • hvplot.extension() loads one or more extensions and makes the first one active. Importing an accessor such as hvplot.pandas calls it to load Bokeh.

  • hvplot.output() switches the active extension among the loaded ones.

HoloViews keeps a separate set of options for each extension, and hvPlot fills the set of the extension that is active when the plot is created. That is why plots should be created after choosing the extension. For the steps, see How to Load and Switch Plotting Extensions.

How HoloViews options work#

A HoloViews element holds the data, not its styling. How it is drawn is set by options that HoloViews stores apart from the element, separately for each extension. The same Curve can carry Bokeh options and Matplotlib options at once, and only those of the extension that renders it are used.

Each element type is drawn by a plotting class of each extension, for example Bokeh and Matplotlib each have their own CurvePlot, and this class declares the options the element accepts. They fall into three groups:

  • Plot options are the parameters of the plotting class, like width, title or show_grid. HoloViews uses them to build the figure. Many have the same name for every extension, but not all: Matplotlib has no width and height and sizes plots with fig_size and aspect.

  • Style options are listed in the style_opts attribute of the plotting class and passed on to the plotting library, like line_dash with Bokeh and linestyle with Matplotlib.

  • Norm options, framewise and axiswise, set whether axis and color ranges are computed per frame of an animation and per plot of a layout, or shared.

The .opts() method accepts options of all groups mixed together. It sets them for the active extension, the one returned by hv.Store.current_backend, unless the backend argument names another one. Options the target extension doesn’t accept are dropped with a warning or raise an error. For example, a line plot can be styled for both Bokeh and Matplotlib:

plot = df.hvplot.line(x='x', y='y')
plot = plot.opts(line_dash='dashed')  # Bokeh is active
plot = plot.opts(linestyle='dashed', backend='matplotlib')

To target one element type in an overlay or a layout, wrap the options in an option builder, like plot.opts(hv.opts.Curve(line_dash='dashed')). hv.help(hv.Curve) lists the plot and style options of Curve for the active extension, and hv.help(hv.Curve, backend='matplotlib') for another one.

The HoloViews guides cover this in more depth: Applying Customizations for the options system, Customizing Plots for the plot options, and Plotting with Bokeh and Plotting with Matplotlib for each extension.

Generic options and styling options#

hvPlot accepts two kinds of options.

Generic options, such as title, width, xlim or legend, are defined by hvPlot and documented in Plotting Options. hvPlot turns them into HoloViews options, mostly plot options (e.g. grid sets show_grid) and a few norm options (e.g. shared_axes=False sets axiswise=True). Most of them work with every extension because hvPlot translates them: it always sets them for Bokeh and, when another extension is active, converts them. For example, width and height become fig_size and aspect with Matplotlib.

Styling options control how the plot elements are drawn, like the dash pattern of a line or the fill transparency of a bar. hvPlot doesn’t define them: they are the HoloViews style options of the active extension, and hvPlot passes them on. These options mostly mirror the properties of the underlying library (Bokeh glyph properties, Matplotlib artist arguments, Plotly trace properties), so they differ:

  • Per extension, because each library names things its own way:

    What is styled

    Bokeh

    Matplotlib

    Plotly

    Dash pattern of a line plot

    line_dash='dashed'

    linestyle='dashed'

    dash='dash'

    Width of a line plot

    line_width=2

    linewidth=2

    line_width=2

    Outline color of scatter markers

    line_color='black'

    edgecolor='black'

    not available

  • Per plot type, because each plot draws different shapes. A histogram has fill options, like fill_color and fill_alpha with Bokeh, that a line plot doesn’t have.

hvPlot checks the styling options against the list of the active extension, ignores the unknown ones and warns about them with suggestions. hvplot.help() and the reference page of each plot method (e.g. hvplot.hvPlot.line()) list the valid ones. See How to Style Plots by Backend.

The object hvPlot returns is a regular HoloViews object, so calling .opts() on it can set any HoloViews option, including those hvPlot doesn’t expose. These options go straight to HoloViews: hvPlot neither checks nor translates them.

Compatibility mode, a bridge from Bokeh#

Bokeh being the default, a lot of hvPlot code uses Bokeh styling options. Moving such code to Matplotlib or Plotly would mean rewriting these options. The compatibility mode, enabled with e.g. hvplot.extension('matplotlib', compatibility='bokeh'), avoids that. hvPlot then checks the styling options against Bokeh’s, and translates them with the mechanism it already uses for the generic options: a table maps Bokeh option names, and a few values, to their equivalent in the active extension. For example, line_dash='dashed' becomes linestyle='dashed' with Matplotlib and dash='dash' with Plotly.

The translation is best effort. Options without an equivalent, such as fill_alpha with Matplotlib or interactive options like hover_color, are dropped, and values without a translation are passed unchanged. The translation only applies to the options passed to hvPlot, options set afterwards with .opts() must use the names of the target extension. Bokeh is the only source supported. The compatibility mode is convenient to port existing code, while the options of the target extension give full control.

Limitations#

  • The extensions are not supported equally: Bokeh is the most used and tested, followed by Matplotlib and then Plotly.

  • Some features depend on the library. Matplotlib plots are static, so interactive options like hover tooltips have no effect.

  • When neither the generic nor the styling options are enough, backend_opts gives access to the objects created by the underlying library.

This web page was generated from a Jupyter notebook and not all interactivity will work on this website.