streams.Selection1D() doesnt fire when a scatter colored by non-numeric columns is tapped

When a hvplot.scatter is colored by a non-numeric column, the streams.Selection1D() doesnt fire when points are tapped.

holoviews.version = 1.19.1

Here is a MRE:

import panel as pn
import hvplot.pandas
import holoviews as hv
from holoviews import streams
import param

pn.extension()

# Minimal dataset
df = pd.DataFrame({
    'Amount': [100000, 200000, 150000, 300000],
    'Year': [2018, 2019, 2020, 2021],
    'km': [10000, 25000, 50000, 75000],
    'Range': [400, 450, 500, 550],
    'Cat': ['a', 'b', 'b', 'c']
})

class MREApp(param.Parameterized):
    x_axis = param.Selector(objects=['Amount', 'Year'], default='Amount')
    y_axis = param.Selector(objects=['Year', 'Range'], default='Year')
    color_by = param.Selector(objects=['Amount', 'Year', 'km', 'Range', 'Cat'], default='Year')
    tap_stream = streams.Selection1D()

    @param.depends('x_axis', 'y_axis', 'color_by')
    def cross_plot(self):
        if pd.api.types.is_numeric_dtype(df[self.color_by]):
            # This changes the tap_stream.index when a point is clicked:
            color_args = {'c': self.color_by, 'cmap': 'Viridis', 'colorbar': True}
        else:
            # This DOES NOT change the tap_stream.index when a point is clicked:
            color_args = {'by': self.color_by, 'cmap': 'Category20'}
        plot = df.hvplot.scatter(x=self.x_axis, y=self.y_axis, **color_args).opts(
            tools=['tap'], width=600, height=400
        )
        self.tap_stream.source = plot
        return plot

    @param.depends('tap_stream.index')
    def show_selection(self):
        if self.tap_stream.index:
            idx = self.tap_stream.index[0]
            selected = df.iloc[idx]
            return pn.pane.Str(f"Selected Point: {selected.to_dict()}")
        else:
            return pn.pane.Str("No selection")

    def panel(self):
        return pn.Column(
            pn.Param(self.param, widgets={'x_axis': pn.widgets.Select, 'y_axis': pn.widgets.Select, 'color_by': pn.widgets.Select}),
            self.cross_plot,
            self.show_selection
        )

app = MREApp()
pn.serve(app.panel())

by creates an overlay of points, which makes streams ineffective AFAIK (probably should raise a warning/error).

I think you get around this by using a hv.streams.Tap instead of a Selection1D; see Selection1D doesn't support datashaded plots · Issue #6436 · holoviz/holoviews · GitHub for similar issue.

Worked like a charm! Thank you :slight_smile: . The root cause was not obvious to me, so some warning would definitely be helpful

1 Like

It could be a bug.