python - 通过悬停在 Bokeh 中突出显示多个 hex_tiles

标签 python bokeh

我尝试在十六进制图中可视化我的数据。为此,我在图形类中使用了 python bokeh 和相应的 hex_tile 函数。我的数据属于 8 个不同类别之一,每个类别都有不同的颜色。下图显示了当前的可视化效果:

Current Visualization 我想添加当鼠标悬停在元素上时更改元素(最好是它的所有类成员)颜色的可能性。

我知道,这是有可能的,因为 bokeh 本身提供了以下示例: https://docs.bokeh.org/en/latest/docs/gallery/hexbin.html

但是,我不知道如何自己实现它(因为这似乎是 hexbin 函数的一个特性,而不是简单的 hex_tile 函数)

目前我在 ColumnDataSource 中提供我的数据:

source = ColumnDataSource(data=dict(
r=x_row,
q=y_col,
color=colors_array,
ipc_class=ipc_array
))

其中“ipc_class”描述了元素所属的 8 个类之一。 对于鼠标悬停工具提示,我使用了以下代码:

TOOLTIPS = [
("index", "$index"),
("(r,q)", "(@r, @q)"),
("ipc_class", "@ipc_class")
]

然后我将所有内容可视化:

p = figure(plot_width=1600, plot_height=1000, title="Ipc to Hexes with colors", match_aspect=True,
       tools="wheel_zoom,reset,pan", background_fill_color='#440154', tooltips=TOOLTIPS)
p.grid.visible = False
p.hex_tile('q', 'r', source=source, fill_color='color')

我希望可视化添加一个函数,将鼠标悬停在一个元素上将导致以下结果之一: 1. 通过改变颜色高亮显示当前元素 2. 将鼠标悬停在同一类的多个元素上时,通过更改其颜色来突出显示同一类的多个元素 3.当元素悬停在hex_tile元素(或完整类)上时更改外线的颜色

Bokeh 可以实现这些功能中的哪些?我将如何实现?

编辑: 在尝试重新实现 Tony 的建议后,只要我的鼠标点击图表,所有元素都会变成粉红色,并且颜色不会变回。我的代码如下所示:

source = ColumnDataSource(data=dict(
    x=x_row,
    y=y_col,
    color=colors_array,
    ipc_class=ipc_array
))

p = figure(plot_width=800, plot_height=800, title="Ipc to Square with colors", match_aspect=True,
           tools="wheel_zoom,reset,pan", background_fill_color='#440154')
p.grid.visible = False
p.hex_tile('x', 'y', source=source, fill_color='color')

###################################

code = ''' 
for (i in cb_data.renderer.data_source.data['color'])
    cb_data.renderer.data_source.data['color'][i] = colors[i];

if (cb_data.index.indices != null) {
    hovered_index = cb_data.index.indices[0];
    hovered_color = cb_data.renderer.data_source.data['color'][hovered_index];
    for (i = 0; i < cb_data.renderer.data_source.data['color'].length; i++) {
        if (cb_data.renderer.data_source.data['color'][i] == hovered_color)
            cb_data.renderer.data_source.data['color'][i] = 'pink';
    }
}
cb_data.renderer.data_source.change.emit();
'''

TOOLTIPS = [
    ("index", "$index"),
    ("(x,y)", "(@x, @y)"),
    ("ipc_class", "@ipc_class")
]

callback = CustomJS(args=dict(colors=colors), code=code)
hover = HoverTool(tooltips=TOOLTIPS, callback=callback)
p.add_tools(hover)
########################################

output_file("hexbin.html")

show(p)

基本上,我从 figure 函数中删除了工具提示,并将它们放到悬停工具中。因为我的图表中已经有红色,所以我将悬停颜色替换为“粉红色”。由于我不太确定“code”变量中的每一行应该做什么,所以我对此很无助。我认为一个错误可能是,我的 ColumnDataSource 看起来与 Tony 的有所不同,我不知道做了什么来“分类”第一个和第三个元素,以及第二个和第四个元素。对我来说,如果分类由“ipc_class”变量完成,那就太完美了。

最佳答案

继上一篇文章的讨论之后,这里出现了针对 OP 代码 (Bokeh v1.1.0) 的解决方案。我所做的是:

1) 添加了一个悬停工具

2) 向 HoverTool 添加了一个 JS 回调:

  • 将十六进制颜色重置为原始颜色(回调中传递的colors_array)
  • 检查当前悬停的十六进制索引(hovered_index)
  • 获取当前悬停的十六进制的ip_class (hovered_ip_class)
  • 遍历 data_source.data['ip_class'] 并找到与悬停的六边形具有相同 ip_class 的所有六边形并为其设置新颜色(粉色)
  • 发送source.change.emit()信号给BokehJS更新模型

The code:

from bokeh.plotting import figure, show, output_file
from bokeh.models import ColumnDataSource, CustomJS, HoverTool

colors_array = ["green", "green", "blue", "blue"]
x_row = [0, 1, 2, 3]
y_col = [1, 1, 1, 1]
ipc_array = ['A', 'B', 'A', 'B']

source = ColumnDataSource(data = dict(
    x = x_row,
    y = y_col,
    color = colors_array,
    ipc_class = ipc_array
))

p = figure(plot_width = 800, plot_height = 800, title = "Ipc to Square with colors", match_aspect = True,
           tools = "wheel_zoom,reset,pan", background_fill_color = '#440154')
p.grid.visible = False
p.hex_tile('x', 'y', source = source, fill_color = 'color')

###################################
code = ''' 
for (let i in cb_data.renderer.data_source.data['color'])
    cb_data.renderer.data_source.data['color'][i] = colors[i];

if (cb_data.index.indices != null) {
    const hovered_index = cb_data.index.indices[0];
    const hovered_ipc_class = cb_data.renderer.data_source.data['ipc_class'][hovered_index];
    for (let i = 0; i < cb_data.renderer.data_source.data['ipc_class'].length; i++) {
        if (cb_data.renderer.data_source.data['ipc_class'][i] == hovered_ipc_class)
            cb_data.renderer.data_source.data['color'][i] = 'pink';
    }
}
cb_data.renderer.data_source.change.emit();
'''

TOOLTIPS = [
    ("index", "$index"),
    ("(x,y)", "(@x, @y)"),
    ("ipc_class", "@ipc_class")
]

callback = CustomJS(args = dict(ipc_array = ipc_array, colors = colors_array), code = code)
hover = HoverTool(tooltips = TOOLTIPS, callback = callback)
p.add_tools(hover)
########################################

output_file("hexbin.html")

show(p)

结果:

enter image description here

关于python - 通过悬停在 Bokeh 中突出显示多个 hex_tiles,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55947149/

相关文章:

python - 打开终端,运行 python 脚本并保持打开状态以获得结果?

python - 为什么我从 HoloViews 保存的 Datashader 绘图的分辨率这么低?

python - Bokeh :列数据源部分给出错误

python - 在 Bokeh 中使用 HoverTool 将本地镜像嵌入相对路径

python - 为应用程序编写单元测试的模拟 redis

python - 获取并显示 numpy 数组中一堆 3 channel 图像中的一个图像

python - 从 Pylons 发送电子邮件

Python Bokeh附加Y轴问题

python-3.x - 如何在没有 'bokeh server --show' 命令的情况下运行 Bokeh 服务器?

python - 变量和函数帮助//Python