带滑块过滤器的直方图 [英] Histogram with slider filter

查看:67
本文介绍了带滑块过滤器的直方图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个带有密度图的直方图,并在散景中使用滑块滤镜进行组合.自动取款机,我有块用另一个线程的密度图创建散景直方图.我不知道如何创建回调函数来更新数据并重新渲染图.

I would like to create a histogram with a density plot combined in bokeh with a slider filter. Atm, I have the blocks to create a bokeh histogram with a density plot from another thread. I dont know how to create the callback function to update the data and rerender the plot.

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中实现回调的方法有两种:

There are two ways to implement callbacks in Bokeh:

  • 使用 JS代码.在那种情况下,图仍然是一个独立的对象,约束条件是您需要在Javascript中进行任何数据操作(该语句有一个小警告,但此处不相关:scipy不能从此类回调中调用)
  • 通过在 Bokeh服务器中执行回调,在这种情况下,您可以使用完整的python工具库.付出的代价是,与第一种情况相比,绘制和分布图要花更多的钱(但这并不困难,请参见示例).
  • with JS code. In that case, the plot remains a standalone object, the constraint being you need to do any data manipulation within Javascript (there is a small caveat to that statement but not relevant here: scipy can't be called from such a callback)
  • by having the callback executed in Bokeh server, in which case you have the full arsenal of python available to you. The cost being, there's a bit more to plotting and distributing the graph than in the first case (but it's not difficult, see example).

考虑到每次更改过滤条件都需要重新调整kde,第二种方法是唯一的选择(除非您想在javascript中进行此操作...).

Considering you need to refit the kde each time you change the filter condition, the second way is the only option (unless you want to do that in javascript...).

这就是您要执行的操作(例如cyl上的过滤器):

That's how you would do it (example with a filter on cyl):

from bokeh.application import Application
from bokeh.application.handlers import FunctionHandler
from bokeh.io import output_notebook, show
from bokeh.layouts import column
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, Select
from bokeh.sampledata.autompg import autompg as df

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

output_notebook()

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)

    def update(attr, old, new):
        if new == 'All':
            filtered_df = df
        else:
            condition = df.cyl == int(new)
            filtered_df = df[condition]

        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 = Select(title='# cyl', value='All', options=['All'] + [str(i) for i in df.cyl.unique()])
    select.on_change('value', update)
    doc.add_root(column(select, p))

# To run it in the notebook:
plot = Application(FunctionHandler(modify_doc))
show(plot)

# Or to run it stand-alone with `bokeh serve --show myapp.py`
# in which case you need to remove the `output_notebook()` call
# from bokeh.io import curdoc
# modify_doc(curdoc())

一些注意事项:

  • 该文件可以在jupyter笔记本中运行(请参见output_notebook()和最后未注释的两行).
  • 要在外部运行它,请注释笔记本行(请参见上文),并取消最后两行的注释.然后,您可以从命令行运行它.
  • Select将仅处理str值,因此您需要进行转换(创建时)和转换(使用值时:oldnew)
  • 对于多个过滤器,您需要同时访问每个Select的状态.您可以通过在定义update函数之前实例化Select来实现(但是还没有任何回调!)并保留对其的引用,使用your_ref.value访问其值并以此建立条件.在update定义之后,您可以在每个Select上附加回调.
  • this is made to be run in jupyter notebook (see the output_notebook() and the last uncommented two lines).
  • to run it outside, comment the notebook lines (see above) and uncomment the last two lines. Then you can run it from the command line.
  • Select will only handle str values so you need to convert in (when creating it) and out (when using the values: old and new)
  • for multiple filters, you need to access the state of each Select at the same time. You do that by instantiating the Selects before defining the update function (but without any callbacks, yet!) and keeping a reference to them, access their value with your_ref.value and build your condition with that. After the update definition, you can then attach the callback on each Select.

最后,是一个具有多个选择的示例:

Finally, an example with multiple selects:

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))

这篇关于带滑块过滤器的直方图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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