python - 在 Python 和 Bokeh 中选择 K;滑块小部件未更新 Python 代码
问题描述
我正在尝试使用 Python 创建一个聚类函数,并使用 Bokeh 上的滑块小部件进行交互。滑块小部件允许用户选择 K 的值(即要查找的集群数)。
这是代码示例:-
from bokeh.models.annotations import Label
import numpy as np
from sklearn import cluster, datasets
from sklearn.preprocessing import StandardScaler
from bokeh.layouts import column, row
from bokeh.plotting import figure, output_file, show
from bokeh.models import CustomJS, Select, Slider
from bokeh.io import curdoc
print("\n\n*** This example may take several seconds to run before displaying. ***\n\n")
N = 50000
PLOT_SIZE = 400
# generate datasets.
np.random.seed(0)
noisy_circles = datasets.make_circles(n_samples=N, factor=.5, noise=.04)
noisy_moons = datasets.make_moons(n_samples=N, noise=.05)
centers = [(-2, 3), (2, 3), (-2, -3), (2, -3)]
blobs1 = datasets.make_blobs(centers=centers, n_samples=N, cluster_std=0.4, random_state=8)
blobs2 = datasets.make_blobs(centers=centers, n_samples=N, cluster_std=0.7, random_state=8)
colors = np.array([x for x in ('#00f', '#0f0', '#f00', '#0ff', '#f0f', '#ff0')])
colors = np.hstack([colors] * 20)
k_slider = Slider(title = "Select K", value=3, start = 2, end = 6)
k = k_slider.value
kmeans = cluster.KMeans(n_clusters= k)
def update_k(attr,old,new):
k = k_slider.value
kmeans = cluster.KMeans(n_clusters= k)
return kmeans
k_slider.on_change('value', update_k)
algorithm = kmeans
plots =[]
for dataset in (noisy_circles, noisy_moons, blobs1, blobs2):
X, y = dataset
X = StandardScaler().fit_transform(X)
algorithm.fit(X)
if hasattr(algorithm, 'labels_'):
y_pred = algorithm.labels_.astype(int)
else:
y_pred = algorithm.predict(X)
p = figure(output_backend="webgl", title=algorithm.__class__.__name__,width=PLOT_SIZE, height=PLOT_SIZE)
p.circle(X[:, 0], X[:, 1], color=colors[y_pred].tolist(), alpha=0.1,)
plots.append(p)
layout = column(k_slider,row(plots[:2]), row(plots[2:]))
output_file("clustering.html", title="clustering with sklearn")
curdoc().add_root(layout)
K 的默认值为 3,但我希望滑块小部件将其更改为 2-6 之间的任何值。我用 bokeh serve 启动了这个应用程序,它显示了带有 3 个可视化集群的图。但是,当我更改滑块时,它不允许我更新绘图。
我咨询了以下内容:-
但我的问题的解决方案并不明显。谁能告诉我/添加我的代码缺少什么?
非常感谢 :)
解决方案
- 更新散景图意味着更新
data_source
它的渲染器,在本例中为circle
. 所以你需要这样做:
plots[0].renderers[0].data_source.data['x'] = NEW_X[:, 0]
plots[0].renderers[0].data_source.data['y'] = NEW_X[:, 1]
plots[0].renderers[0].data_source.change.emit()
和colors
...一样
看起来您需要
for
在 Python 回调中重复整个循环,algorithm
这kmeans
取决于K
. 如果您K
的平均聚类数和每个聚类由一个图表示,则意味着您需要动态删除/添加图,依赖于K
.因此,如果 2) 为真,则无需在回调中更新现有图,但您可以尝试删除现有
root
图并添加包含新图的新图。所以在你的回调中你可以这样做:
def update_k(attr,old,new):
k = k_slider.value
kmeans = cluster.KMeans(n_clusters= k)
plots =[]
for dataset in (noisy_circles, noisy_moons, blobs1, blobs2):
...
plots.append(p)
curdoc().remove_root()
curdoc().add_root(column(k_slider,row(plots[:2]), row(plots[2:])))
它应该可以工作,但请务必查阅有关如何使用remove_root()的文档
或者,您可以操纵/替换以下内容而不是删除根目录layout.children
[k_slider, row1, row2]
推荐阅读
- python - 如何使用 engine='openpyxl' 使 pandas.read_excel 的行为与 xlrd 一样,默认情况下不显示纳秒?
- java - 在 protobuf 中,我可以将地图的键限制为某些值吗?
- javascript - 如何验证来自 Google 发布/订阅推送的 JWT 令牌(未找到信封的 pem)
- c# - 如何将列名数组传递给 linq 查询
- javascript - History.push 适用于 BrowserRouter 但不适用于路由器
- r - 使用 actionButton Shiny R 删除 outputTable
- sql-server - 如何在 SQL Server Reporting Service 2017 中启用 REST API?
- oracle - “ON CONVERSION ERROR”因“ORA-43918:此参数必须是文字”而失败
- jquery - 带有 jQuery/数据表的 Django
- c++ - GetDIBits() 将目标指针设置为 NULL 且没有错误