Python 带滑块滤波器的直方图

Python 带滑块滤波器的直方图,python,bokeh,Python,Bokeh,我想创建一个直方图,密度图与滑块过滤器组合在一起。Atm,我用另一个线程的密度图创建了一个博克直方图。我不知道如何创建回调函数来更新数据和重新渲染绘图 from bokeh.io import output_file, show from bokeh.plotting import figure from bokeh.sampledata.autompg import autompg as df from numpy import histogram, linspace from scipy.

我想创建一个直方图,密度图与滑块过滤器组合在一起。Atm,我用另一个线程的密度图创建了一个博克直方图。我不知道如何创建回调函数来更新数据和重新渲染绘图

from bokeh.io import output_file, show
from bokeh.plotting import figure
from bokeh.sampledata.autompg import autompg as df

from numpy import histogram, linspace
from scipy.stats.kde import gaussian_kde

pdf = gaussian_kde(df.hp)

x = linspace(0,250,50)

p = figure(plot_height=300)
p.line(x, pdf(x))

# plot actual hist for comparison
hist, edges = histogram(df.hp, density=True, bins=20)
p.quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:], alpha=0.4)

show(p)

在Bokeh中实现回调有两种方法:

具有在这种情况下,plot仍然是一个独立的对象,约束是您需要在Javascript中执行任何数据操作。该语句有一个小警告,但与此无关:不能从这样的回调调用scipy 通过在中执行回调,在这种情况下,您可以使用完整的python库。成本是,与第一种情况相比,绘制和分发图形要多一些,但并不困难,请参见示例。 考虑到每次更改过滤条件时都需要重新安装kde,第二种方法是唯一的选择,除非您想在javascript中这样做

这就是使用cyl上的过滤器的示例:

请注意:

这是为了在jupyter笔记本中运行,请参阅output_笔记本和最后未注释的两行。 要在外部运行,请注释上面的笔记本行,并取消注释最后两行。然后可以从命令行运行它。 Select将只处理str值,因此在创建时需要将其转换为in,而在使用值(旧值和新值)时需要将其转换为out 对于多个过滤器,您需要同时访问每个选择的状态。您可以通过在定义更新函数之前实例化Selects来实现这一点,但是还没有任何回调!并保留对它们的引用,使用您的_ref.value访问它们的值,并使用该值构建您的条件。在更新定义之后,您可以在每个选择上附加回调。 最后,一个具有多个选项的示例:

def modify_doc(doc):
    x = linspace(0,250,50)

    source_hist = ColumnDataSource({'top': [], 'left': [], 'right': []})
    source_kde = ColumnDataSource({'x': [], 'y': []})

    p = figure(plot_height=300)
    p.line(x='x', y='y', source=source_kde)
    p.quad(top='top', bottom=0, left='left', right='right', alpha=0.4, source=source_hist)
    select_cyl = Select(title='# cyl', value='All', options=['All'] + [str(i) for i in df.cyl.unique()])
    select_ori = Select(title='origin', value='All', options=['All'] + [str(i) for i in df.origin.unique()])

    def update(attr, old, new):
        all = pd.Series(True, index=df.index)
        if select_cyl.value == 'All':
            cond_cyl = all
        else:
            cond_cyl = df.cyl == int(select_cyl.value)
        if select_ori.value == 'All':
            cond_ori = all
        else:
            cond_ori = df.origin == int(select_ori.value)
        filtered_df = df[cond_cyl & cond_ori]

        hist, edges = histogram(filtered_df.hp, density=True, bins=20)
        pdf = gaussian_kde(filtered_df.hp)

        source_hist.data = {'top': hist, 'left': edges[:-1], 'right': edges[1:]}
        source_kde.data = {'x': x, 'y': pdf(x)}

    update(None, None, 'All')

    select_ori.on_change('value', update)
    select_cyl.on_change('value', update)

    doc.add_root(column(select_ori, select_cyl, p))

谢谢你的回复。正确理解您对多重Fitler的看法,因为这正是我现在努力实现的目标。我在更新之前定义了两个选择器,如下所示:select=Selecttitle='cyl',value='All',options=['All']+[stri for I in df.cyl.unique]和select_2=Selecttitle=Car name,value=All,options['All']+df.name.unique,并用condition=df替换condition=df.cyl==intnew行[df.cyl==select.val&df.name==select_2.val]添加了一个示例。我使用了origin而不是name,因为名称几乎是唯一的,所以kde对名称过滤后的df没有意义。
def modify_doc(doc):
    x = linspace(0,250,50)

    source_hist = ColumnDataSource({'top': [], 'left': [], 'right': []})
    source_kde = ColumnDataSource({'x': [], 'y': []})

    p = figure(plot_height=300)
    p.line(x='x', y='y', source=source_kde)
    p.quad(top='top', bottom=0, left='left', right='right', alpha=0.4, source=source_hist)
    select_cyl = Select(title='# cyl', value='All', options=['All'] + [str(i) for i in df.cyl.unique()])
    select_ori = Select(title='origin', value='All', options=['All'] + [str(i) for i in df.origin.unique()])

    def update(attr, old, new):
        all = pd.Series(True, index=df.index)
        if select_cyl.value == 'All':
            cond_cyl = all
        else:
            cond_cyl = df.cyl == int(select_cyl.value)
        if select_ori.value == 'All':
            cond_ori = all
        else:
            cond_ori = df.origin == int(select_ori.value)
        filtered_df = df[cond_cyl & cond_ori]

        hist, edges = histogram(filtered_df.hp, density=True, bins=20)
        pdf = gaussian_kde(filtered_df.hp)

        source_hist.data = {'top': hist, 'left': edges[:-1], 'right': edges[1:]}
        source_kde.data = {'x': x, 'y': pdf(x)}

    update(None, None, 'All')

    select_ori.on_change('value', update)
    select_cyl.on_change('value', update)

    doc.add_root(column(select_ori, select_cyl, p))