hvPlot is a high-level plotting API that provides a familiar interface similar to pandas .plot() but generates interactive Bokeh plots. It works with pandas DataFrames, xarray, and many other data structures.
Why hvPlot?
- Interactive by Default: Zoom, pan, hover without extra code
- Familiar API: If you know pandas plotting, you know hvPlot
- Flexible Output: Bokeh, Matplotlib, or Plotly backends
- Dashboard Ready: Integrates with Panel for dashboards
- Multi-Format: Works with pandas, xarray, GeoPandas, NetworkX
Basic Usage
Simple Interactive Plots
import pandas as pd
import hvplot.pandas # Adds .hvplot accessor
# Load data
df = pd.read_csv('data.csv')
# Interactive line plot (just like .plot() but interactive)
df.hvplot.line(x='time', y='value', width=800, height=400)
# Interactive scatter plot with hover
df.hvplot.scatter(x='age', y='score', c='group', hover_cols=['name'])
Comparison with Pandas
# Pandas (static)
df.plot(x='time', y='value')
# hvPlot (interactive)
df.hvplot(x='time', y='value')
Common Plot Types
Line Plots
# Single line
df.hvplot.line(x='time', y='voltage')
# Multiple lines
df.hvplot.line(x='time', y=['voltage', 'current'])
# With customization
df.hvplot.line(
x='time',
y='signal',
title='LFP Recording',
xlabel='Time (s)',
ylabel='Voltage (mV)',
width=900,
height=400,
color='blue'
)
Scatter Plots
# Basic scatter
df.hvplot.scatter(x='x_coord', y='y_coord')
# Color by category
df.hvplot.scatter(x='x', y='y', c='category', cmap='Category10')
# Size by value
df.hvplot.scatter(x='x', y='y', s='size', scale=0.5)
# Custom hover information
df.hvplot.scatter(
x='x', y='y',
hover_cols=['name', 'value', 'group']
)
Histograms and Distributions
# Histogram
df.hvplot.hist('reaction_time', bins=30)
# Kernel density estimate
df.hvplot.kde('reaction_time')
# Distribution by group
df.hvplot.hist('score', by='condition', alpha=0.5)
Heatmaps
# Correlation matrix
corr_matrix = df.corr()
corr_matrix.hvplot.heatmap(cmap='RdBu_r', clim=(-1, 1))
# Time-frequency representation
spectrogram_df.hvplot.heatmap(
x='time', y='frequency', C='power',
cmap='viridis', colorbar=True
)
Working with Time Series
import pandas as pd
import hvplot.pandas
# Time series with datetime index
df.index = pd.to_datetime(df.index)
# Plot with interactive time selection
df.hvplot.line(x='time', y='value', xlabel='Time', ylabel='Signal')
# Multiple channels
channels = ['Ch1', 'Ch2', 'Ch3', 'Ch4']
df.hvplot.line(x='time', y=channels, ylabel='LFP (mV)')
xarray Integration
import xarray as xr
import hvplot.xarray
# Load multi-dimensional data
ds = xr.open_dataset('recording.nc')
# Interactive 2D plot with sliders for other dimensions
ds['lfp'].hvplot.image(x='time', y='channel', cmap='RdBu_r')
# Line plot with interactive dimension selection
ds['power'].hvplot.line(x='frequency', groupby='channel')
# Quadmesh for irregular grids
ds.hvplot.quadmesh(x='time', y='frequency', z='power', cmap='viridis')
Combining Multiple Plots
Overlays
# Overlay plots using *
plot1 = df1.hvplot.line(x='time', y='signal1', label='Control')
plot2 = df2.hvplot.line(x='time', y='signal2', label='Treatment')
plot1 * plot2
Layouts
# Side-by-side using +
plot1 + plot2
# Vertical layout
plot1 + plot2
# Complex layouts
(plot1 + plot2) + (plot3 + plot4)
Advanced Features
Interactive Widgets
# GroupBy for interactive dimension selection
df.hvplot.line(x='time', y='signal', groupby='trial')
# This creates a widget to select different trials
Custom Styling
df.hvplot.scatter(
x='x', y='y',
color='blue',
size=50,
alpha=0.6,
title='My Plot',
fontsize={'title': 16, 'labels': 14, 'xticks': 10, 'yticks': 10},
grid=True
)
Geographic Data
import hvplot.pandas
# Plot with map tiles
gdf.hvplot.points(
x='lon', y='lat',
geo=True,
tiles='OSM',
color='red',
size=50
)
Practical Neuroscience Examples
Calcium Imaging Traces
# Interactive calcium trace explorer
traces_df.hvplot.line(
x='time',
y='dF_F',
groupby='roi', # Widget to select ROIs
xlabel='Time (s)',
ylabel='ΔF/F',
width=900,
height=400
)
Spike Raster Plot
# Raster plot with interactive hover
spikes_df.hvplot.scatter(
x='time',
y='unit_id',
hover_cols=['unit_id', 'time', 'trial'],
s=1,
color='black',
ylabel='Unit',
xlabel='Time (s)'
)
LFP Power Spectra
# Compare power spectra across conditions
power_df.hvplot.line(
x='frequency',
y='power',
by='condition',
logy=True,
xlabel='Frequency (Hz)',
ylabel='Power',
legend='top_right'
)
Explorer Functionality
# Create an interactive explorer with all plot types
from hvplot import explorer
explorer = df.hvplot.explorer()
explorer # Interactive GUI to try different plot types
Integration with Panel
hvPlot works seamlessly with Panel for dashboards:
import panel as pn
# Create plot
plot = df.hvplot.line(x='time', y='value')
# Create dashboard
dashboard = pn.Column(
'# My Dashboard',
plot
)
dashboard.servable()
Backends
import hvplot.pandas
# Use Bokeh (default)
hvplot.extension('bokeh')
# Use Matplotlib for static plots
hvplot.extension('matplotlib')
# Use Plotly
hvplot.extension('plotly')
Installation
pixi add hvplot
# or
conda install -c conda-forge hvplot
# or
pip install hvplot
Best Practices
- Use descriptive labels and titles
- Include relevant columns in hover_cols for context
- Set appropriate width and height for readability
- Use groupby for exploring multi-dimensional data
- Combine with Panel for interactive dashboards
- Choose colormaps that are colorblind-friendly
- Cache large plots for better performance
- Use .opts() for fine-grained control when needed