This is a common cookbook example.
I have two data frames that are related. One is represented as points ( geo data but for simple example that has been left out) and the other data frame is say associated time series for the “selected” point.
I have a working example, but it feels inefficient, because I am linking the streams via a param called “selected”. Please help me improve
Attaching the jupyter notebook as well as displaying it here
import numpy as np
import pandas as pd
import holoviews as hv
hv.extension('bokeh')
from holoviews import opts
import hvplot.pandas
import param as param
import panel as pn
pn.extension()
np.random.seed(12) # to allow repitition with same random values
npts = 10
dfpts = pd.DataFrame(np.random.rand(npts,2))
dfpts.head()
nts=20 # number of time series points
dfmatching=pd.DataFrame(np.random.rand(nts, npts), pd.date_range('01-01-2000',periods=nts))
dfmatching.head()
class MapSelect(param.Parameterized):
selected = param.List(default=[0], doc='selection')
line_color = param.Color(doc='Line Color', default='#FF0000')
def __init__(self, dfpts, dfmatching, **kwargs):
super().__init__(**kwargs) # on't foget to call super init!
self.dfpts=dfpts
self.dfmatching=dfmatching
self.points = dfpts.hvplot.points().opts(opts.Points(tools=['tap'], size=5)) # add tap to allow user interactive select
self.select_stream = hv.streams.Selection1D(source=self.points, index=[0]) # stream to attach to points plot
self.select_stream.add_subscriber(self.set_selected) # callback to a method here to set selection
# Feels inefficient. Is there a better way of linking the view method to both stream and param changes
def set_selected(self, index):
self.selected = index
def viewpts(self):
return self.points
@param.depends('selected', 'line_color')
def view(self):
if self.selected is None or self.selected==None:
self.selected=[0] # set to first index if empty ? How to handle empty selections
fi=self.selected[0] # making it easy by just doing the first selection. One could do an overlay of all
pts_selected=self.dfpts.iloc[fi,:] # select by iloc (thats how Selection1D works)
common_on=pts_selected.name # this common_on could be an property on which to select dfmatching values
return dfmatching.iloc[:,common_on].hvplot(color=self.line_color)
ms=MapSelect(dfpts, dfmatching)
pn.Column(ms.viewpts, ms.param.line_color, ms.view)