Understanding Grouping and Coloring Options#

This guide explains the key differences between hvPlot’s three main approaches to handling categorical data: groupby, by, and color/c. Understanding these differences is important for creating effective visualizations and choosing the right approach for your specific use case. These options expect long data, where the categories are values in a column.

Overview of the Three Approaches#

hvPlot provides three primary ways to handle categorical data in your plots:

  1. groupby: Creates interactive widgets with HoloMap / DynamicMap containers

  2. by: Creates multiple plot elements in NdOverlay or NdLayout containers

  3. color/c: Creates vectorized coloring within a single plot element

Each approach produces different outputs, offers different interaction capabilities, and has different performance characteristics.

import hvplot.pandas #noqa

penguins = hvplot.sampledata.penguins("pandas").dropna()
penguins.head(3)
species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g sex year
0 Adelie Torgersen 39.1 18.7 181.0 3750.0 male 2007
1 Adelie Torgersen 39.5 17.4 186.0 3800.0 female 2007
2 Adelie Torgersen 40.3 18.0 195.0 3250.0 female 2007

groupby: Interactive Widgets#

The groupby parameter creates interactive widgets that allow users to filter and explore different subsets of your data dynamically.

What it creates:#

  • HoloViews containers: HoloMap or DynamicMap object

  • Interactive widgets: Automatically generated based on data type

  • Single view at a time: Only one category visible per interaction

When to use:#

  • When you want to explore different subsets of data interactively

  • When you have many categories that would clutter a single plot

  • When building dashboards or interactive reports

  • When you need to reduce visual complexity

plot_groupby = penguins.hvplot.scatter(
    x='bill_length_mm',
    y='bill_depth_mm',
    groupby='species',
    title="Groupby: Interactive Widget",
    width=400,
    dynamic=False, # loads all the data on the frontend to enable interactivity on the fly
)
plot_groupby

Indexing and Access#

When you use groupby, hvPlot creates a HoloViews container object (HoloMap or DynamicMap) that acts like a dictionary. This container stores separate plot elements for each category value, which is why you can “index into” specific categories.

Why indexing works: The container maps category values (like 'Adelie', 'Chinstrap', 'Gentoo') to individual plot elements. Each category becomes a “key” that you can use to access its corresponding plot.

What happens when you index: You extract a single plot element from the container, giving you just the data for that specific category without the interactive widget.

Use cases:

  • Extract specific categories for further analysis

  • Combine individual categories in custom layouts

  • Access the underlying plot element for advanced customization

# Access specific category: plot['category_value']
adelie_only = plot_groupby['Adelie']  # Shows only Adelie penguins
print(f"Type of groupby plot: {type(plot_groupby)}")
print(f"Type of specific species: {type(adelie_only)}")
adelie_only
Type of groupby plot: <class 'holoviews.core.spaces.HoloMap'>
Type of specific species: <class 'holoviews.element.chart.Scatter'>

by: Multiple Plot Elements#

The by parameter creates multiple plot elements shown simultaneously, either overlaid or in separate subplots.

What it creates:#

  • NdOverlay: Multiple elements overlaid (default)

  • NdLayout: Separate subplots when subplots=True

  • All categories visible: Simultaneously displayed

When to use:#

  • When you want to compare categories side-by-side

  • When you have a manageable number of categories (typically < 10)

  • When color differentiation is sufficient for your analysis

  • When you need all data visible at once

overlay_plot = penguins.hvplot.scatter(
    x='bill_length_mm',
    y='bill_depth_mm',
    by='species',
    title="By: Overlaid Elements"
)
overlay_plot
plot_by_subplots = penguins.hvplot.scatter(
    x='bill_length_mm',
    y='bill_depth_mm',
    by='species',
    width=300,
    subplots=True,
)
plot_by_subplots.cols(2)

Indexing and Access#

Similar to groupby, using by creates a HoloViews container object (NdOverlay or NdLayout) that you can index into. However, the behavior is different because all elements are displayed simultaneously.

Why indexing works: The NdOverlay/NdLayout container stores individual plot elements for each category, just like a dictionary mapping category values to plot elements.

What happens when you index: You extract a single plot element from the overlay/layout. This gives you just that category’s data as a standalone plot element, separate from the others.

Key difference from groupby: While groupby shows one category at a time with widgets, by shows all categories together, but you can still extract individual elements in the same way as groupby objects.

# Access specific category: plot['category_value']
adelie_element = overlay_plot['Adelie']  # Returns just the element for Adelie penguins
print(f"Type of 'by' plot: {type(overlay_plot)}")
print(f"Type of specific species element: {type(adelie_element)}")
adelie_element
Type of 'by' plot: <class 'holoviews.core.overlay.NdOverlay'>
Type of specific species element: <class 'holoviews.element.chart.Scatter'>

color/c: Vectorized Coloring#

The color parameter creates vectorized coloring within a single plot element, where each data point is colored based on the category value.

What it creates:#

  • Single plot element: One unified Scatter, Curve, etc.

  • Vectorized coloring: Each point colored by category

  • Cannot be indexed: Single element, not separable by category

When to use:#

  • When you want the best performance for large datasets

  • When you need smooth, continuous color mapping

  • When you don’t need to isolate specific categories

plot_color = penguins.hvplot.scatter(
    x='bill_length_mm',
    y='bill_depth_mm',
    color='species',
    title="Color: Vectorized Coloring"
)
plot_color

Indexing and Access#

Unlike groupby and by, using color creates a single plot element rather than a container object. This means indexing by category is not possible.

Why indexing doesn’t work: There’s no container structure - just one plot element where the color information is stored as data within the element itself. The categories exist as color mappings, not as separate, accessible plot elements.

What this means: All your data points are part of one unified plot object. The categorical information is encoded in the visual properties (colors) rather than the data structure.

Implications:

  • You cannot programmatically separate categories

  • Better performance since there’s only one plot element to render

  • All data is always visible

  • Ideal when you want aesthetic grouping without interactive separation

print(f"Type of 'color' plot: {type(plot_color)}")
try:
    adelie_color = plot_color['Adelie']  # This will raise an error.
except Exception:
    print("Error: You cannot index a single element by category!")
Type of 'color' plot: <class 'holoviews.element.chart.Scatter'>
Error: You cannot index a single element by category!

Understanding Container Objects vs Single Elements#

The key concept underlying these differences is how HoloViews organizes your data:

Container Objects (indexable)#

  • groupby → HoloMap/DynamicMap: {category: plot_element}

  • by → NdOverlay/NdLayout: {category: plot_element}

These containers act like dictionaries where each category value maps to a separate plot element. This structure enables indexing with plot['category_name'].

Single Elements (not indexable)#

  • color → Single plot element (Scatter, Curve, etc.)

Here, all data points belong to one plot element. Categories are encoded as visual properties (colors) rather than separate data structures.

This fundamental difference affects not just indexing, but also performance, interactivity, and how you can manipulate the resulting plots.

Visual Output Comparison#

Let’s compare all three approaches side by side to see the differences:

import panel as pn

width = 300

groupby_plot = penguins.hvplot.scatter(
    x='bill_length_mm', y='bill_depth_mm',
    groupby='species', title="groupby='species'",
    frame_width=width, widget_location='bottom_right',
    shared_axes=False,
)

by_plot = penguins.hvplot.scatter(
    x='bill_length_mm', y='bill_depth_mm',
    by='species', title="by='species'",
    frame_width=width,
)

color_plot = penguins.hvplot.scatter(
    x='bill_length_mm', y='bill_depth_mm',
    color='species', title="color='species'",
    frame_width=width,
)

pn.Column(pn.Row(groupby_plot, by_plot), color_plot)

Key Visual Differences:#

  • groupby='species' shows only one species at a time with a widget

  • by='species' shows all species overlaid with different colors and a legend

  • color='species' looks similar to by but is a single plot element

When using subplots=True with by, you get separate panels:

penguins.hvplot.scatter(
    x='bill_length_mm', y='bill_depth_mm',
    by='species', subplots=True,
    width=300, height=250,
)

Advanced: Combining Approaches#

You can combine these approaches for more complex visualizations:

penguins.hvplot.scatter(
    x='bill_length_mm', y='bill_depth_mm',
    groupby='island', color='species',
    width=500, height=400, dynamic=False,
    title="Groupby island, colored by species"
)

This is useful when you want to explore one dimension (island) while maintaining visual differentiation of another (species).

Summary#

Aspect

groupby

by

color/c

Holoviews Object

HoloMap / DynamicMap

NdOverlay / NdLayout

Single Element

Interactivity

Widget-based

Static overlay

Static single plot

Indexing

plot['category']

plot['category']

Not available

Faceting the plot elements

Not available

subplots=True

Not available

Performance

Variable

Medium

Best

Visual

One at a time

All simultaneous

All simultaneous

Use case

Exploration

Comparison

Performance/Aesthetics

Choose the approach that best matches your needs:#

  • Use groupby for interactive exploration of many categories

  • Use by for direct comparison of manageable categories

  • Use color for performance with large datasets or aesthetic coloring

Further Reading

See the HoloViews Reference Manual for more information on the various objects created by a hvPlot plot.

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