两个交互式散景图:在一个图形中选择一个值,然后更改另一个图形 [英] Two interactive bokeh plots: select a value in one graph and change the other

查看:89
本文介绍了两个交互式散景图:在一个图形中选择一个值,然后更改另一个图形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个交互式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))

推荐答案

@bigreddot最终帮助我找到了这个

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆