我试图调整答案:Get selected data contained within box select tool in Bokeh
但得到:
NameError: name 'inds' is not defined
选择积分后。
有谁知道最近发生了什么?
我正在使用的代码:
import pandas as pd
import numpy as np
import matplotlib as mpl
from bokeh.transform import factor_cmap, linear_cmap
from bokeh.palettes import Spectral6
from bokeh.plotting import figure, output_file, show
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.io import output_notebook
import bokeh.plotting as bpl
import bokeh.models as bmo
from bokeh.models.tools import *
output_notebook()
algorithm = 'Loc'
metric = 'LengthOfStayDaysNBR'
coordinate_df = pd.DataFrame({'x-{}'.format(str(algorithm)[:3]):np.random.rand(500)\
,'y-{}'.format(str(algorithm)[:3]):np.random.rand(500)\
,metric:np.random.rand(500)})
TOOLS="pan,wheel_zoom,reset,hover,poly_select,lasso_select"
p = figure(title = '{}'.format(str(algorithm)[:3]),tools=TOOLS)
source = bpl.ColumnDataSource(coordinate_df)
if metric == 'LengthOfStayDaysNBR':
color_mapper = linear_cmap(metric,palette=Spectral6,low=coordinate_df[metric].min(),high=coordinate_df[metric].max())
else:
color_mapper = factor_cmap(metric,palette=Spectral6,factors=coordinate_df[metric].unique())
p1 = figure(width=250, height = 250, title = '{}'.format(str(algorithm)[:3]),tools=TOOLS)
p1.scatter('x-{}'.format(str(algorithm)[:3]),'y-{}'.format(str(algorithm)[:3]),fill_color= color_mapper, source = source)
source.callback = CustomJS(args=dict(source=source), code="""
var inds = cb_obj.get('selected')['1d'].indices;
var d1 = cb_obj.get('data');
console.log(d1)
var kernel = IPython.notebook.kernel;
IPython.notebook.kernel.execute("inds = " + inds);
"""
)
show(p1)
# Run this after selecting
for x,y in zip([source.data['x-{}'.format(str(algorithm)[:3])][i] for i in inds],
[source.data['y-{}'.format(str(algorithm)[:3])][i] for i in inds]):
print(x,y)
给出一些背景知识:我试图从包含许多特征的较大数据框中获取x / y坐标,选择散点图的子群组,然后绘制(在条形图中)最大(20个左右)平均值的图形子群组的指定x / y坐标的特征。例如,假设您有50个要素(列)和20个数据点的子群组。我想要剩下的48个功能'平均值用条形图绘制成条形图'表示特征平均值的高度。知道怎么做吗? - user123328 10小时前
此外:能够将实际的索引/ xy坐标恢复到某个对象,即数据帧,np.array,列表或其他任何东西,这将是很棒的 - user123328 10小时前
编辑:
我得到了(有点)使用以下内容:
def app(doc):
x = df_algs['x-{}'.format(str(algorithm)[:3])]
y = df_algs['y-{}'.format(str(algorithm)[:3])]
# create the scatter plot
if metric == 'LengthOfStayDaysNBR':
color_mapper = linear_cmap(metric,palette=Spectral6,low=df_algs[metric].min(),high=df_algs[metric].max())
else:
color_mapper = factor_cmap(metric,palette=Spectral6,factors=df_algs[metric].unique())
source = ColumnDataSource(dict(
x = x
, y = y
, metric_ = df_algs[metric]))
# create the scatter plot
p = figure(tools=TOOLS, plot_width=600, plot_height=600, min_border=10, min_border_left=50,
toolbar_location="above", x_axis_location=None, y_axis_location=None,
title="Linked Histograms")
p.select(BoxSelectTool).select_every_mousemove = False
p.select(LassoSelectTool).select_every_mousemove = False
r = p.scatter('x', 'y', source=source, fill_color = color_mapper, alpha=0.6)
#
# create the horizontal histogram
hhist, hedges = np.histogram(x, bins=20)
hzeros = np.zeros(len(hedges)-1)
hmax = max(hhist)*1.1
LINE_ARGS = dict(color="#3A5785", line_color=None)
ph = figure(toolbar_location=None, plot_width=p.plot_width, plot_height=200, x_range=p.x_range,
y_range=(-hmax, hmax), min_border=10, min_border_left=50, y_axis_location="right")
ph.xgrid.grid_line_color = None
ph.yaxis.major_label_orientation = np.pi/4
ph.background_fill_color = "#fafafa"
ph.quad(bottom=0, left=hedges[:-1], right=hedges[1:], top=hhist, color="white", line_color="#3A5785")
hh1 = ph.quad(bottom=0, left=hedges[:-1], right=hedges[1:], top=hzeros, alpha=0.5, **LINE_ARGS)
hh2 = ph.quad(bottom=0, left=hedges[:-1], right=hedges[1:], top=hzeros, alpha=0.1, **LINE_ARGS)
# create the vertical histogram
vhist, vedges = np.histogram(y, bins=20)
vzeros = np.zeros(len(vedges)-1)
vmax = max(vhist)*1.1
pv = figure(toolbar_location=None, plot_width=200, plot_height=p.plot_height, x_range=(-vmax, vmax),
y_range=p.y_range, min_border=10, y_axis_location="right")
pv.ygrid.grid_line_color = None
pv.xaxis.major_label_orientation = np.pi/4
pv.background_fill_color = "#fafafa"
pv.quad(left=0, bottom=vedges[:-1], top=vedges[1:], right=vhist, color="white", line_color="#3A5785")
vh1 = pv.quad(left=0, bottom=vedges[:-1], top=vedges[1:], right=vzeros, alpha=0.5, **LINE_ARGS)
vh2 = pv.quad(left=0, bottom=vedges[:-1], top=vedges[1:], right=vzeros, alpha=0.1, **LINE_ARGS)
layout = column(row(p, pv), row(ph, Spacer(width=200, height=200)))
doc.add_root(layout)
doc.title = "Selection Histogram"
def update(attr, old, new):
inds = np.array(new['1d']['indices'])
if len(inds) == 0 or len(inds) == len(x):
hhist1, hhist2 = hzeros, hzeros
vhist1, vhist2 = vzeros, vzeros
else:
neg_inds = np.ones_like(x, dtype=np.bool)
neg_inds[inds] = False
hhist1, _ = np.histogram(x[inds], bins=hedges)
vhist1, _ = np.histogram(y[inds], bins=vedges)
hhist2, _ = np.histogram(x[neg_inds], bins=hedges)
vhist2, _ = np.histogram(y[neg_inds], bins=vedges)
hh1.data_source.data["top"] = hhist1
hh2.data_source.data["top"] = -hhist2
vh1.data_source.data["right"] = vhist1
vh2.data_source.data["right"] = -vhist2
df = df_algs.loc[df_algs.index.isin(inds)]
df.drop(expected_metrics+metrics+['AgeNBR'],axis=1).mean().sort_values(ascending=False)[:25].plot(kind='Bar')
plt.show()
r.data_source.on_change('selected', update)
但
if metric == 'LengthOfStayDaysNBR':
color_mapper = linear_cmap(metric,palette=Spectral6,low=df_algs[metric].min(),high=df_algs[metric].max())
else:
color_mapper = factor_cmap(metric,palette=Spectral6,factors=df_algs[metric].unique())
似乎打破了代码。我得到" Glyph指的是不存在的列名:{}"在尝试对散点图进行颜色编码时。
答案 0 :(得分:1)
我不会依赖调用CustomJS
的{{1}}回调来执行此操作。我认为这是一种非常脆弱的做事方式,当以任意顺序重新执行单元格时,容易混淆或不合理。此外,为了将来考虑,我不确定它是否会与下一代JupyterLab一起工作,因为kernel.execute
可能无法使用。
相反,我会嵌入一个真实的Bokeh Server Application。 Bokeh服务器专门用于通过定义和维护的协议高效且稳健地同步Bokeh的JavaScript和Python部分之间的数据,并提供基于任一方的更改执行回调。
这是嵌入在笔记本中的app的截屏视频gif,它根据中心图中的选择更新一对直方图。代码单元格在gif下面给出。
单元格1
kernel.execute
单元格2
import numpy as np
from bokeh.io import output_notebook, show
from bokeh.layouts import row, column
from bokeh.models import BoxSelectTool, LassoSelectTool, Spacer
from bokeh.plotting import figure, curdoc
output_notebook()
第3小组
x1 = np.random.normal(loc=5.0, size=400) * 100
y1 = np.random.normal(loc=10.0, size=400) * 10
x2 = np.random.normal(loc=5.0, size=800) * 50
y2 = np.random.normal(loc=5.0, size=800) * 10
x3 = np.random.normal(loc=55.0, size=200) * 10
y3 = np.random.normal(loc=4.0, size=200) * 10
x = np.concatenate((x1, x2, x3))
y = np.concatenate((y1, y2, y3))
TOOLS="pan,wheel_zoom,box_select,lasso_select,reset"
第4小组
def app(doc):
# create the scatter plot
p = figure(tools=TOOLS, plot_width=600, plot_height=600, min_border=10, min_border_left=50,
toolbar_location="above", x_axis_location=None, y_axis_location=None,
title="Linked Histograms")
p.background_fill_color = "#fafafa"
p.select(BoxSelectTool).select_every_mousemove = False
p.select(LassoSelectTool).select_every_mousemove = False
r = p.scatter(x, y, size=3, color="#3A5785", alpha=0.6)
# create the horizontal histogram
hhist, hedges = np.histogram(x, bins=20)
hzeros = np.zeros(len(hedges)-1)
hmax = max(hhist)*1.1
LINE_ARGS = dict(color="#3A5785", line_color=None)
ph = figure(toolbar_location=None, plot_width=p.plot_width, plot_height=200, x_range=p.x_range,
y_range=(-hmax, hmax), min_border=10, min_border_left=50, y_axis_location="right")
ph.xgrid.grid_line_color = None
ph.yaxis.major_label_orientation = np.pi/4
ph.background_fill_color = "#fafafa"
ph.quad(bottom=0, left=hedges[:-1], right=hedges[1:], top=hhist, color="white", line_color="#3A5785")
hh1 = ph.quad(bottom=0, left=hedges[:-1], right=hedges[1:], top=hzeros, alpha=0.5, **LINE_ARGS)
hh2 = ph.quad(bottom=0, left=hedges[:-1], right=hedges[1:], top=hzeros, alpha=0.1, **LINE_ARGS)
# create the vertical histogram
vhist, vedges = np.histogram(y, bins=20)
vzeros = np.zeros(len(vedges)-1)
vmax = max(vhist)*1.1
pv = figure(toolbar_location=None, plot_width=200, plot_height=p.plot_height, x_range=(-vmax, vmax),
y_range=p.y_range, min_border=10, y_axis_location="right")
pv.ygrid.grid_line_color = None
pv.xaxis.major_label_orientation = np.pi/4
pv.background_fill_color = "#fafafa"
pv.quad(left=0, bottom=vedges[:-1], top=vedges[1:], right=vhist, color="white", line_color="#3A5785")
vh1 = pv.quad(left=0, bottom=vedges[:-1], top=vedges[1:], right=vzeros, alpha=0.5, **LINE_ARGS)
vh2 = pv.quad(left=0, bottom=vedges[:-1], top=vedges[1:], right=vzeros, alpha=0.1, **LINE_ARGS)
layout = column(row(p, pv), row(ph, Spacer(width=200, height=200)))
doc.add_root(layout)
doc.title = "Selection Histogram"
def update(attr, old, new):
inds = np.array(new['1d']['indices'])
if len(inds) == 0 or len(inds) == len(x):
hhist1, hhist2 = hzeros, hzeros
vhist1, vhist2 = vzeros, vzeros
else:
neg_inds = np.ones_like(x, dtype=np.bool)
neg_inds[inds] = False
hhist1, _ = np.histogram(x[inds], bins=hedges)
vhist1, _ = np.histogram(y[inds], bins=vedges)
hhist2, _ = np.histogram(x[neg_inds], bins=hedges)
vhist2, _ = np.histogram(y[neg_inds], bins=vedges)
hh1.data_source.data["top"] = hhist1
hh2.data_source.data["top"] = -hhist2
vh1.data_source.data["right"] = vhist1
vh2.data_source.data["right"] = -vhist2
r.data_source.on_change('selected', update)