How do I delete my selected point dynamically from other points in a mapview using holoviews Datalink

@ahuang11 I’m sorry for late response. I tried your solution insert my code. And It works well. I delete point , change Rxy value. that’s why your solution works well.

Screen shot [ Before delete ]

Screen shot [ After delete : Rxy value is changed by calculation ]

My final code

from typing import Any
from bokeh.models.annotations import Title
import hvplot.pandas  # noqa
import numpy as np
import pandas as pd
import panel as pn
import param
import holoviews as hv
from numpy.random import *

INDICES = ["v1", "v2", "v3", "v4"]
memory = set([])
#------------------------------------------------------------------------------------
# Definition ReactiveTable Class
#------------------------------------------------------------------------------------
class ReactiveTable(pn.viewable.Viewer):
    table = param.DataFrame()  # x,y table
    count = param.Integer()    # number of items
    random = param.Action(lambda x: x.param.trigger("random"), label="Random")
    x = param.ObjectSelector(INDICES[0], objects=INDICES, label="x")  # selector x
    y = param.ObjectSelector(INDICES[1], objects=INDICES, label="y")  # selector y
    int_list                = param.ListSelector(default=[3, 5], objects=[1, 3, 5, 7, 9], precedence=0.5)    
    Autocomplete_area = pn.widgets.AutocompleteInput(name='Autocomplete Input', options=INDICES, placeholder='Write something here')    
    table_widget = param.Parameter()  # to get table_widget.selection to work in depends
    Toggle_tf = param.Boolean() # <--- 20211220 add Toggle_tf param
    from holoviews import opts
    from holoviews import streams   
    selection = streams.Selection1D()   
    memory = set([])    
    first_flag = False ## Tap First Flag   

    def __init__(self, **params):
        super().__init__(**params)
        self.table_widget = pn.Param(self.param.table)[0]
        self.Toggle = pn.widgets.Toggle.from_param(self.param.Toggle_tf,name='Push Toggle', button_type='default') # <<-- 20211220 add button_widget  

    def change_data(self) :
        size = np.random.randint(10, 15)
        nums = np.random.randint(5, 10)                      # <--- 2021/12/06  Change nums of items 
        self.count = nums                                    # <--- 2021/12/06  Display nums of items
        INDICES = [ str('v'+str(i)) for i in range(nums) ]   # <--- 2021/12/06  Make a new indices list
        # self.table = pd.DataFrame(
        # {i: np.random.randint(1, 100, size) for i in INDICES}
        # ).T
        test = pd.DataFrame(
        {i: np.arange(1, 100, size) for i in INDICES}) # numpy.arange([start, ]stop, [step, ]dtype = None)
        test.iloc[2]['v0']=test.iloc[2]['v0']/(rand()+1)     
        test.iloc[3]['v0']=test.iloc[3]['v0']*(rand()+1)      
        self.table = test.T
        self.param.x.objects = INDICES   # change selector x lists
        self.param.y.objects = INDICES   # change selector y lists
        self.Autocomplete_area.options = INDICES

    # Definition click random button
    #@param.depends("random", watch=True, on_init=True)
    @param.depends('Toggle_tf',watch=True, on_init=True)
    def _fill_table_with_random_data(self):
        if hasattr(self, "tabs") : 
            self.memory=[]
            self.first_flag = True                 
            if self.Toggle_tf == True :       
                self.change_data()
                self.Toggle.name = 'Finish'
                self.Toggle.button_type = 'primary'           
            else :
                self.Toggle.name = 'Push Toggle'
                self.Toggle.button_type = 'default'
                 
        else :
            self.change_data()

    # Definition click table widget
    @param.depends("table_widget.selection", watch=True)
    def _set_x_with_table_selection(self):
        OBJECT = (self.param.x.objects)
        if self.table_widget.selection:
            self.x = OBJECT[self.table_widget.selection[0]]           
            if hasattr(self, "tabs") : self.tabs.active = 0  # if it is not initial , self has tabs objects. so change active tab=0 
        else:
            self.x = OBJECT[0]
           
    
        # self.count += 1 # <--- 2021/12/06 Comment out

    # Definition select x value
    @param.depends("x",watch=True)
    def _set_table_selection_with_x(self):
        OBJECT = (self.param.x.objects)
        self.table_widget.selection = [OBJECT.index(self.x)]
        self.Autocomplete_area.value = self.x
        self.memory=[]  
        self.first_flag = True            

    @param.depends("Autocomplete_area.value",watch=True)
    def _set_table_selection_with_Autocomplete_area(self):
        OBJECT = (self.Autocomplete_area.options)
        sel = self.Autocomplete_area.value
        if (sel in OBJECT) : 
            self.table_widget.selection = [OBJECT.index(self.Autocomplete_area.value)]
            self.memory=[]
            self.first_flag = True              

    # Definition select x,y value or click random button
#    @param.depends("x", "y", "random")
    @param.depends("x", "y", "selection.index" , 'Toggle_tf')

    def plot(self):        
        index = self.selection.index
        if self.first_flag == True or self.Toggle_tf == True :
            index = []
            self.first_flag = False
        print ('debug', index)
        df = pd.DataFrame ({"x": self.table.loc[self.x], "y": self.table.loc[self.y]})
        for i in index:
            self.memory.append(i)  # add previous indices
        df2 = df.loc[~df.index.isin(self.memory)]  # remove all past indices  
        new_graph = hv.Scatter(df2, "x", "y").opts(size=5, color="yellow")  # plot              
        #相関係数を計算
        x_corr = df2['x'].to_numpy().tolist() 
        y_corr = df2['y'].to_numpy().tolist()
        # 相関行列を計算
        coef = np.corrcoef(x_corr, y_corr)
        # 相関行列を表示
        print('20220105 Debug correlation value : ',coef)
        a, b = np.polyfit(x_corr, y_corr, 1)  
        if b>0 :
            plot_title = 'Rxy='+str(coef[0][1])[0:4] + ' : y='+str(a)[0:5]+'x+'+str(b)[0:5] 
        else :
            plot_title = 'Rxy='+str(coef[0][1])[0:5] + ' : y='+str(a)[0:5]+'x'+str(b)[0:6]               
        graph_1 = self.table.T.hvplot.scatter(
            x=self.x, y=self.y, color="red", grid=True, xlim=(0, 100), ylim=(0, 100) 
        ).opts(toolbar='below',size=8, title=plot_title, tools=['tap','box_select', 'lasso_select'])
        graph_2 =  hv.Slope(a, b).opts(color='green', line_width=4 , line_dash='dashed')
        # Declare points as source of selection stream   
        self.selection.source=graph_1        

        plot = graph_1 * graph_2 * new_graph
        return plot

    # Definition update data table
    @param.depends("table")
    def table_list(self):
        return pn.pane.DataFrame(self.table, sizing_mode="fixed")

    # https://holoviews.org/reference/apps/bokeh/selection_stream.html
    # https://holoviews.org/reference/containers/bokeh/DynamicMap.html

    # Definition panel layout
    def __panel__(self):
        # Layout
        graph_layout = pn.Row(
            pn.Column(
                pn.pane.Markdown("## Update table"),
                self.param.x,
                self.Autocomplete_area,
                self.param.y,
                # self.param.random,
                self.Toggle,
            ),
            pn.panel(pn.Row(self.plot), sizing_mode="fixed"),
        )
        list_layout = pn.Column(self.table_widget, self.param.count, self.param.random)

        self.tabs = pn.Tabs(
            ("Graph", graph_layout),
            ("List", list_layout),
            active=self.tabs.active if hasattr(self, "tabs") else 0,
        )

        return pn.template.FastListTemplate(
            site="Panel",
            main=self.tabs,
            title="Panel Sample",
            theme="dark",
        )

# run app
if __name__ == "__main__":
    app = ReactiveTable()
    app.show(port=5007)
elif __name__.startswith("bokeh"):
    app = ReactiveTable()
    app.servable()

Thanks for your kindness

2 Likes