hvplot#

The core functionality provided by hvPlot is a simple and high-level plotting interface (API), modeled on Pandas’s .plot API and extended in various ways leveraging capabilities offered by the packages of the HoloViz ecosystem, most notably HoloViews. hvPlot can generate interactive plots with either Bokeh (default) or Plotly, or static plots with Matplotlib. hvPlot supports many data libraries of the Python ecosystem:

  • Pandas: DataFrame, Series (columnar/tabular data)

  • XArray: Dataset, DataArray (labelled multidimensional arrays)

  • GeoPandas: GeoDataFrame (geometry data)

  • Rapids cuDF: GPU DataFrame, Series (columnar/tabular data)

  • Polars: DataFrame, LazyFrame, Series (columnar/tabular data)

  • Dask: DataFrame, Series (distributed/out of core arrays and columnar data)

  • Streamz: DataFrame(s), Series(s) (streaming columnar data)

  • Intake: DataSource (data catalogues)

  • Ibis: DataFrame interface for many backends (DuckDB, SQLite, SnowFlake, etc.)

  • NetworkX: Graph (network graphs)

Register .hvplot#

Let’s create a simple Pandas DataFrame we’ll plot later.

import numpy as np
import pandas as pd
np.random.seed(1)

idx = pd.date_range('1/1/2000', periods=1000)
df = pd.DataFrame(np.random.randn(1000, 4), index=idx, columns=list('ABCD')).cumsum()
df.head(2)
A B C D
2000-01-01 1.624345 -0.611756 -0.528172 -1.072969
2000-01-02 2.489753 -2.913295 1.216640 -1.834176

The most convenient way to use hvPlot is to register the .hvplot accessor on the data type you are working with. This is done with a special import of the form import hvplot.<data library>.

import hvplot.pandas  # noqa

In addition to registering the .hvplot accessor on Pandas objects (DataFrame and Series), the import above sets the Bokeh plotting library as the default one and loads its corresponding extension.

Note

In a notebook, loading the extension means that there’s actually some front-end code that is injected in the cell output of the import, this code being required for HoloViews plots to behave correctly. So make sure not to remove this cell!

Now simply call .hvplot() on the DataFrame as you would call Pandas’ .plot().

first_plot = df.hvplot()
first_plot

The same process can be applied to other libraries, we’ll just show another example with Xarray.

import hvplot.xarray  # noqa
import xarray as xr

air_ds = xr.tutorial.open_dataset('air_temperature').load()
air_ds['air'].isel(time=slice(0, 1000, 60)).hvplot.image(dynamic=False)

Bokeh plots#

As you can see, the default plots hvPlot generate are Bokeh plots. These plots are interactive and support panning, zooming, hovering, and clickable/selectable legends. It’s worth spending some time getting used to interact with this kind of plot, try for instance zooming in on an axis and see what happens!

first_plot

hvplot namespace#

The .hvplot namespace holds the range of supported plot methods (e.g. line, scatter, hist, etc.). Use tab completion to explore the available plot types.

df.hvplot.<TAB>

Similarly to Panda’s API, every plot method accepts a wide range of parameters. You can explore them by calling hvplot.help('line') or using tab completion:

df.hvplot.line(<TAB>

Compose plots#

The object returned by a .hvplot.<type>() call is a HoloViews object.

plot1 = df['A'].hvplot.area(alpha=0.2, color='red', width=300)
plot2 = df['B'].hvplot.line(width=300)
print(plot2)
:Curve   [index]   (B)

HoloViews objects can easily composed using the + and * operators:

  • <plot1> + <plot2> lays the plots out in a row container

  • (<plot1> + <plot2>).cols(1) lays the plots out in a column container

  • <plot1> * <plot2> overlays the plots

plot1 + plot2
plot1 * plot2

Widgets-based exploration#

from bokeh.sampledata.penguins import data as df_penguins
df_penguins.head(2)
species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g sex
0 Adelie Torgersen 39.1 18.7 181.0 3750.0 MALE
1 Adelie Torgersen 39.5 17.4 186.0 3800.0 FEMALE

The groupby parameter allows to explore a dimension of the data using widgets.

df_penguins.hvplot.scatter(x='bill_length_mm', y='bill_depth_mm', groupby=['island', 'sex'], dynamic=False)

Display large data#

NUM = 1_000_000
dists = [
    pd.DataFrame(dict(x=np.random.normal(x, s, NUM), y=np.random.normal(y, s, NUM)))
     for x,  y,    s in [
       ( 5,  2, 0.20), 
       ( 2, -4, 0.10), 
       (-2, -3, 0.50), 
       (-5,  2, 1.00), 
       ( 0,  0, 3.00)]
]
df_large_data = pd.concat(dists, ignore_index=True)
len(df_large_data)
5000000

hvPlot provides multiple ways to display arbitrarily large datasets. The most versatile option depends on Datashader (optional dependency) and simply consists of setting rasterize to True. The plot returned is an image, each pixel of that image being colorized based on the number of points it contains; which means that all the points contribute to the image. This plot is also dynamic, zooming in and out and panning leads to a recomputation of the image. Luckily, this all happens really fast! The plot below is generated with no less than 5 million points.

df_large_data.hvplot.points('x', 'y', rasterize=True, cnorm='eq_hist', aspect=1, colorbar=False)

Geographic plots#

hvPlot can generate geographic plots and handle geographic data (e.g. GeoPandas DataFrame) thank to GeoViews (optional dependency).

import cartopy.crs as crs

proj = crs.Orthographic(-90, 30)
air_ds.air.sel(time='2013-06-01 12:00').hvplot.quadmesh(
    'lon', 'lat', projection=proj, project=True,
    global_extent=True, cmap='viridis', coastline=True
)
/usr/share/miniconda/envs/hvplotdocs/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/110m_physical/ne_110m_coastline.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)

Matplotlib or Plotly plots#

hvPlot offers the possibility to create Matplotlib and Plotly plots. Load the chosen plotting library with the extension function.

hvplot.extension('matplotlib')
air_ds.air.isel(time=slice(0, 9, 3)).hvplot.quadmesh(
    'lon', 'lat', projection=proj, project=True, global_extent=True, 
    cmap='viridis', rasterize=True, dynamic=False, coastline=True,
    xaxis=None, yaxis=None, width=370
)

Conclusion#

We have briefly explored some of the main features of .hvplot(). There’s a lot more to it! For more information on using .hvplot() take a look at the Bokeh Plotting Guide and the various plotting guides available.

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