Interactive filtering of DataFrame

Hello,

I feel like this should be in the cookbook somewhere, but I cannot find it. I’m trying to display a scatter plot and data frame, and filter the displayed data frame by selecting elements of the scatter plot.

So far I have this:

import holoviews as hv
import panel as pn
import pandas as pd
import numpy as np

hv.extension('bokeh')

# Generate random data
num_points = 100
np.random.seed(42)  # For reproducibility
x = np.random.rand(num_points)
y = np.random.rand(num_points)
colors = np.random.rand(num_points)

# Create a DataFrame
df = pd.DataFrame({
    'x': x,
    'y': y,
    'color': colors
})

# Create a Holoviews Points element for the scatter plot
scatter = hv.Points(df, kdims=['x', 'y'], vdims=['color']).opts(color="color", tools=["tap"])

# Create a Panel DataFrame widget to display the DataFrame
df_table = pn.widgets.DataFrame(df, name='DataFrame')

# Create a layout with scatter plot and data frame side by side
layout = pn.Row(scatter, df_table)

layout.servable()

This only gets so far as putting the scatter plot side by side. I’d like to add a stream (I think Tap) and use it (with pn.bind? Or is that wrong?). The table should then only display selected values.

OK, here is one way of doing this:

import numpy as np
import pandas as pd
import panel as pn

hv.extension("bokeh")

# Generate random data
num_points = 100
np.random.seed(42)
x = np.random.rand(num_points)
y = np.random.rand(num_points)
colors = np.random.rand(num_points)

# Create a DataFrame
df = pd.DataFrame({"x": x, "y": y, "color": colors})

# Create a Holoviews Points element for the scatter plot
scatter = hv.Points(df, kdims=["x", "y"], vdims=["color"]).opts(tools=["tap"], size=10)

# Create a Tap stream to capture clicks
tap_stream = hv.streams.Tap(source=scatter)

# Create a Panel DataFrame widget to display the DataFrame
df_table = pn.widgets.DataFrame(df, name="DataFrame")


# Define a function to update the DataFrame based on the clicked point
def update_df(click_event_x, click_event_y):
    # Find the closest point in the DataFrame to the clicked coordinates
    distances = (
        (df["x"] - click_event_x.new) ** 2 + (df["y"] - click_event_y.new) ** 2
    ) ** 0.5
    closest_index = distances.idxmin()

    # Create a DataFrame for the selected point
    selected_df = df.loc[[closest_index]]
    return selected_df


# Define a function to update the DataFrame widget
def update_table(x, y):
    df_table.value = update_df(x, y)


# Bind the update function to the Tap stream
tap_stream.param.watch(update_table, ["x", "y"])

# Display the scatter plot and data frame
layout = pn.Row(scatter, df_table)
layout.servable()

Some more similar
Filter Histogram and Table based on Selections from Scatter Plot - Panel - HoloViz Discourse

Filter tabulator on plot zoom / select - Panel - HoloViz Discourse

Bi-directional Link with Tabulator and Plot - Panel - HoloViz Discourse