Bokeh回调是否更新了列表而不是ColumnDataSource

Have Bokeh Callback update a list instead of a ColumnDataSource?

本文关键字:ColumnDataSource 列表 回调 是否 更新 Bokeh      更新时间:2023-09-26

我的问题与修改Bokeh Gallery中的此示例有关。

我有一个矩阵m或原始数据,其中每一行都对应于变换空间中的一对x,y坐标(请参阅代码的#MockData部分(。

x,y坐标绘制在左侧图上。我试图更改示例,以便在左图中选择一些点时,右图将显示相应行的折线图。

我已经将问题缩小到了这一点,右图将显示"索引"列表指定的所需数据。然而,我不知道如何将回调函数链接到索引列表。(当前回调使用索引无用地更新源s2。(

复制时代码应该工作:

from bokeh.plotting import figure, output_file, show, ColumnDataSource, hplot
from bokeh.models import HoverTool, Callback, ColumnDataSource
import pandas as pd
output_file("Map.html")
# Mock data
m = np.zeros((6,11))
for i in range(6):
    for j in range(11):
        m[i,j] = i+j
x = [0,1,2,3,4,5]; y = [0,2,4,6,8,10]
m0 = m.transpose()
m1 = pd.DataFrame(m0, index=['0','1','2','3','4','5','6','7','8','9','10'], columns=[np.arange(0,len(m),1).astype(str)])
#First plot
s1 = ColumnDataSource(data=dict(x=x,y=y))
p1 = figure(tools=["lasso_select"], plot_width=600, plot_height=400)
p1.scatter('x', 'y', fill_color='black', line_color=None, size=10, source=s1)
#Second plot
s2 = ColumnDataSource(data=dict(z=[]))
p2 = figure(plot_width=400, plot_height=400)    
m1 = ColumnDataSource(m1)
indices = [1,3,4]
for i in indices:
    p2.line(np.arange(0,11,1), '%s'%i ,  source=m1)
s1.callback = Callback(args=dict(s2=s2), code="""
  var inds = cb_obj.get('selected')['1d'].indices;
  var d2 = s2.get('data');
  d2['z'] = []
  for (i = 0; i < inds.length; i++) {
      d2['z'].push(inds[i])}
  s2.trigger('change'); 
""")
layout = hplot(p1, p2)
show(layout)

原始问题:

使用Bokeh文档中的示例。我试图从左侧窗口中的选择中获取索引,并使用它们从具有原始数据的矩阵中获取适当的行,并绘制该行。详细信息:

我从一个值矩阵开始,其中每列是一年,每行是一个位置。我在矩阵上运行sklearn谱嵌入来表征数据,并得到一个矩阵,其中每一列都以某种方式描述数据。我将前3列绘制为x、y坐标和颜色。接下来,我将尝试修改示例,这样,当我选择一些点时,第二个图将它们的原始数据(行(显示为单独的线。以下是主要取自该示例的相关代码

如果我误解了你的问题,请告诉我,但听起来你有一个矩阵(我们称之为m1(,你正在对其进行转换,并在s1中生成数据,在p1中绘制。您希望能够选择p1中的一些数据,并将m1中的相应数据绘制在p2中。

如果是这样的话,您将需要三个ColumnDataSource对象。您必须为m1创建一个ColumnDataSource,并使用您已经拥有的s1和s2。回调需要类似于:

s1.callback = Callback(args=dict(m1=m1, s2=s2), code="""
  var inds = cb_obj.get('selected')['1d'].indices;
  var d1 = m1.get('data');
  var d2 = s2.get('data');
  d2['x'] = []
  d2['y'] = []
  for (i = 0; i < inds.length; i++) {
    d2['x'].push(d1['x'][inds[i]])
    d2['y'].push([inds[i]])
  }
  s2.trigger('change'); 
""")

这将获取所选数据的索引,并找到具有相同索引m1(原始数据(的x和y,并将其添加到s2。然后s2.trigger('change'(调用将更新p2中的数据点。

如果我误解了你的问题,请告诉我。

无论是在这里还是在Bokeh邮件列表中都没有任何响应,这让我相信以这种方式使用回调是不可能的,所以我不得不绕过它,接受当前的限制,即无法使回调"大小"动态。

出于数据探索的目的,无论如何都可以这样做。

from bokeh.plotting import figure, output_file, show, ColumnDataSource, hplot
from bokeh.models import HoverTool, Callback, ColumnDataSource
import pandas as pd
output_file("bla.html")
# Mock data
m = np.ones((6,11))
for i in range(2,6):
    for j in range(11):
        m[i,j] = i+j
x = [0,1,2,3,4,5]; y = [0,2,4,6,8,10]
m0 = m.transpose()
m1 = pd.DataFrame(m0, index=['0','1','2','3','4','5','6','7','8','9','10'], columns=[np.arange(0,len(m),1).astype(str)])
#First plot
s1 = ColumnDataSource(data=dict(x=x,y=y))
p1 = figure(tools=["lasso_select"], plot_width=600, plot_height=400)
p1.scatter('x', 'y', fill_color='black', line_color=None, size=10, source=s1)
#Second plot
s2 = ColumnDataSource(data=dict(x=[],y=[],y2=[]))
p2 = figure(plot_width=400, plot_height=400, tools =[])
m1 = ColumnDataSource(m1) #Actual Datasource for the second plot
p2.line(np.arange(0,100,1), 'y' , source=s2) # From original data - series 1
p2.line(np.arange(0,100,1), 'y2' , source=s2) # From original data - series 2
s1.callback = Callback(args=dict(s2=s2, m1=m1), code="""
  var inds = cb_obj.get('selected')['1d'].indices;
  var d1 = m1.get('data'); 
  var d2 = s2.get('data');
  d2['y'] = []
  d2['y2'] = []
  for (i = 0; i < 11; i++) {
    d2['y'].push(d1[inds['0']][i]),
    d2['y2'].push(d1[inds['1']][i])
  }
  s2.trigger('change'); 
""")
layout = hplot(p1, p2)
show(layout)

代码现在绘制选定数据中前两个索引的原始数据。限制是必须预定义原始数据序列的数量,因此代码只能绘制两行。此外,它还需要至少两行代码才能执行。仅对选定的一个点无效。因此,如果我预定义了更多要绘制的线,我将始终必须选择该数量的点。

相关文章:
  • 没有找到相关文章