两个交互式散景图:在一个图形中选择一个值,然后更改另一个图形 [英] Two interactive bokeh plots: select a value in one graph and change the other
问题描述
我想创建一个交互式python散景图.我有两个通过列名称链接的数据框.
当我在plot1中选择一个条形图时,我想在plot 2中显示属于该列的数据框2(df2)的数据.
例如,df1可以包含df2所有列的均值.如果单击显示的均值,则可以在第二张图中查找构成均值基础的原始数据.
不幸的是,我无法使其正常运行,也找不到可比较的示例.以下是我到目前为止的内容.我认为错误在mycolumn="@colnames"
中,而taptool没有返回我期望的结果.
下面的源代码根据@bigreddot的评论
I want to create an interactive python Bokeh plot. I have two dataframes which are linked by the column names .
When I select a bar in plot1 I want to show in plot 2 the data of dataframe 2 (df2) that belong to that column.
For example the df1 could contain the mean of all columns of df2. If you click on the displayed mean you can sea in the second graph the rawdata that formed the basis for the mean.
Unfortunately I cannot get it working and I could not find a comparable example. Below is what I have so far. I assume the error is in mycolumn="@colnames"
and the taptool is not returning what I expect.
Source code below updated according to @bigreddot 's comment
import pandas as pd
import numpy as np
from bokeh.models import ColumnDataSource, TapTool
from bokeh.plotting import figure
from bokeh.layouts import row
#from bokeh.plotting import show
from bokeh.io import curdoc
# data for plot 2
df2 = pd.DataFrame({"A" : np.linspace(10, 20, 10),
"B" : np.linspace(20, 30, 10),
"C" : np.linspace(30, 40, 10),
"D" : np.linspace(40, 50, 10),
"E" : np.linspace(50, 60, 10),})
source2 = ColumnDataSource(
data=dict(
x=list(df2.index.values),
y=list(df2.iloc[:,0].values)
)
)
# data for plot 1
df1 = np.mean(df2)
source1 = ColumnDataSource(
data=dict(
x=list(range(0,df1.shape[0])),
y=list(df1.values),
colnames = list(df1.index.values)
)
)
# Plot graph one with data from df1 and source 1 as barplot
plot1 = figure(plot_height=300, plot_width=400, tools="tap")
plot1.vbar(x='x',top='y',source=source1, bottom=0,width =0.5)
# Plot graph two with data from df2 and source 2 as line
plot2 = figure(plot_height=300, plot_width=400, title="myvalues",
tools="crosshair,box_zoom,reset,save,wheel_zoom,hover")
r1 = plot2.line(x='x',y='y',source =source2, line_alpha = 1, line_width=1)
# safe data from plot 2 for later change in subroutine
ds1 = r1.data_source
def update_plot2(mycolumn):
try:
ds1.data['y'] = df2[mycolumn].values
except:
pass
# add taptool to plot1
taptool = plot1.select(type=TapTool)
taptool.callback = update_plot2(mycolumn="@colnames")
#show(row(plot1,plot2))
curdoc().add_root(row(plot1,plot2))
推荐答案
Eventually @bigreddot 's helped me to find this Bokeh Server callback from tools. Below the code which worked for me:
import pandas as pd
import numpy as np
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.layouts import row
from bokeh.io import curdoc
from random import sample
# data for plot 2
df2 = pd.DataFrame({"A" : sample(np.linspace(10, 20, 10),5),
"B" : sample(np.linspace(20, 30, 10),5),
"C" : sample(np.linspace(30, 40, 10),5),
"D" : sample(np.linspace(40, 50, 10),5),
"E" : sample(np.linspace(50, 60, 10),5),})
source2 = ColumnDataSource(
data=dict(
x=list(df2.index.values),
y=list(df2.iloc[:,0].values)
)
)
# data for plot 1
df1 = np.mean(df2)
source1 = ColumnDataSource(
data=dict(
x=list(range(0,df1.shape[0])),
y=list(df1.values),
colnames = list(df1.index.values)
)
)
# Plot graph one with data from df1 and source 1 as barplot
plot1 = figure(plot_height=300, plot_width=400, tools="tap")
barglyph = plot1.vbar(x='x',top='y',source=source1, bottom=0,width =0.5)
# Plot graph two with data from df2 and source 2 as line
plot2 = figure(plot_height=300, plot_width=400, title="myvalues",
tools="crosshair,box_zoom,reset,save,wheel_zoom,hover")
r1 = plot2.line(x='x',y='y',source =source2, line_alpha = 1, line_width=1)
# safe data from plot 2 for later change in subroutine
ds1 = r1.data_source
def callback(attr, old, new):
patch_name = source1.data['colnames'][new['1d']['indices'][0]]
ds1.data['y'] = df2[patch_name].values
print("TapTool callback executed on Patch {}".format(patch_name))
# add taptool to plot1
barglyph.data_source.on_change('selected',callback)
curdoc().add_root(row(plot1,plot2))
这篇关于两个交互式散景图:在一个图形中选择一个值,然后更改另一个图形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!