<jupyter_start><jupyter_text>**Title**: Regression selection**Description**: A linked streams example demonstrating how to the Selection1D stream to tap on a datapoint and reveal a regression plot. Highlights how custom interactivity can be used to reveal more information about a dataset.**Dependencies**: Bokeh, SciPy**Backends**: [Bokeh](./Selection1D_tap.ipynb)<jupyter_code>import numpy as np
import holoviews as hv
from holoviews import opts
from holoviews.streams import Selection1D
from scipy import stats
hv.extension('bokeh')
def gen_samples(N, corr=0.8):
    xx = np.array([-0.51, 51.2])
    yy = np.array([0.33, 51.6])
    means = [xx.mean(), yy.mean()]  
    stds = [xx.std() / 3, yy.std() / 3]
    covs = [[stds[0]**2          , stds[0]*stds[1]*corr], 
            [stds[0]*stds[1]*corr,           stds[1]**2]] 

    return np.random.multivariate_normal(means, covs, N)

data = [('Week %d' % (i%10), np.random.rand(), chr(65+np.random.randint(5)), i) for i in range(100)]
sample_data = hv.NdOverlay({i: hv.Points(gen_samples(np.random.randint(1000, 5000), r2))
                            for _, r2, _, i in data})
points = hv.Scatter(data, 'Date', ['r2', 'block', 'id']).redim.range(r2=(0., 1))
stream = Selection1D(source=points)
empty = (hv.Points(np.random.rand(0, 2)) * hv.Slope(0, 0)).relabel('No selection')

def regression(index):
    if not index:
        return empty
    scatter = sample_data[index[0]]
    xs, ys = scatter['x'], scatter['y']
    slope, intercep, rval, pval, std = stats.linregress(xs, ys)
    return (scatter * hv.Slope(slope, intercep)).relabel('r2: %.3f' % slope)

reg = hv.DynamicMap(regression, kdims=[], streams=[stream])

average = hv.Curve(points, 'Date', 'r2').aggregate(function=np.mean)
layout = points * average + reg
layout.opts(
    opts.Curve(color='black'),
    opts.Slope(color='black', framewise=True),
    opts.Scatter(color='block', tools=['tap', 'hover'], width=600, 
                 marker='triangle', cmap='Set1', size=10, framewise=True),
    opts.Points(frame_width=250),
    opts.Overlay(toolbar='above', legend_position='right')
)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1732394366197183, 'fraction_numerical': 0.03145539906103286, 'mean_word_length': 4.134939759036144, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '327263', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 806, 'n_tokens_neox': 757, 'n_words': 176, 'path': 'examples/reference/streams/bokeh/Selection1D_tap.ipynb', 'repo_name': 'kgullikson88/holoviews', 'size': '2130'}