@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