简体   繁体   English

盒须图上的散景悬停工具提示

[英]Bokeh Hover tooltip on Box-Whisker Plot

I'm new to bokeh, but trying desperately to apply a Hover tooptip to a Box-Whisker plot.我是散景的新手,但我拼命地尝试将 Hover tooptip 应用于 Box-Whisker 情节。 I am trying to display the Q1,Q2,Q3 and IQR values when hovering over the Box glyph but have been unsuccessful in my attempts, and confused by the process of creating the components of a Box-Whisker plot我试图在将鼠标悬停在 Box 字形上时显示 Q1、Q2、Q3 和 IQR 值,但在我的尝试中未成功,并且对创建 Box-Whisker 图的组件的过程感到困惑

I am using the example provided from the bokeh documentations.我正在使用散景文档中提供的示例。

import numpy as np
import pandas as pd
from bokeh.models import ColumnDataSource, Grid, LinearAxis, Plot, Quad,Range1d,HoverTool, Panel, Tabs,Legend, LegendItem
from bokeh.plotting import figure, output_file, show


# generate some synthetic time series for six different categories
cats = list("abcdef")
yy = np.random.randn(2000)
g = np.random.choice(cats, 2000)
for i, l in enumerate(cats):
    yy[g == l] += i // 2
df = pd.DataFrame(dict(score=yy, group=g))

# find the quartiles and IQR for each category
groups = df.groupby('group')
q1 = groups.quantile(q=0.25)
q2 = groups.quantile(q=0.5)
q3 = groups.quantile(q=0.75)
iqr = q3 - q1
upper = q3 + 1.5*iqr
lower = q1 - 1.5*iqr

# find the outliers for each category
def outliers(group):
    cat = group.name
    return group[(group.score > upper.loc[cat]['score']) | (group.score < lower.loc[cat]['score'])]['score']
out = groups.apply(outliers).dropna()

# prepare outlier data for plotting, we need coordinates for every outlier.
if not out.empty:
    outx = []
    outy = []
    for keys in out.index:
        outx.append(keys[0])
        outy.append(out.loc[keys[0]].loc[keys[1]])

p = figure(tools="", background_fill_color="#efefef", x_range=cats, toolbar_location=None)

# if no outliers, shrink lengths of stems to be no longer than the minimums or maximums
qmin = groups.quantile(q=0.00)
qmax = groups.quantile(q=1.00)
upper.score = [min([x,y]) for (x,y) in zip(list(qmax.loc[:,'score']),upper.score)]
lower.score = [max([x,y]) for (x,y) in zip(list(qmin.loc[:,'score']),lower.score)]

# stems
p.segment(cats, upper.score, cats, q3.score, line_color="black")
p.segment(cats, lower.score, cats, q1.score, line_color="black")

# boxes
p.vbar(cats, 0.7, q2.score, q3.score, fill_color="#E08E79", line_color="black")
p.vbar(cats, 0.7, q1.score, q2.score, fill_color="#3B8686", line_color="black")

# whiskers (almost-0 height rects simpler than segments)
p.rect(cats, lower.score, 0.2, 0.01, line_color="black")
p.rect(cats, upper.score, 0.2, 0.01, line_color="black")

# outliers
if not out.empty:
    p.circle(outx, outy, size=6, color="#F38630", fill_alpha=0.6)

p.xgrid.grid_line_color = None
p.ygrid.grid_line_color = "white"
p.grid.grid_line_width = 2
p.xaxis.major_label_text_font_size="16px"

# Format the tooltip
tooltips = [
    ('q1', '@q2'),
    ('q2', '@q1'),
    ('q3', '@q3'),
    ('iqr', '@iqr'),
]

# Add the HoverTool to the figure
p.add_tools(HoverTool(tooltips=tooltips))

output_file("boxplot.html", title="boxplot.py example")

show(p)

在此处输入图片说明

Beyond a few built-in "special" variables, like mouse coordinates, the hover tool expects column names from the ColumnDataSource .除了一些内置的“特殊”变量(如鼠标坐标)之外,悬停工具还需要来自ColumnDataSource列名。 To get access to q1 , q2 , etc. you need to create the boxes using a ColumnDataSource rather than plain arrays.要访问q1q2等,您需要使用ColumnDataSource而不是普通数组来创建框。

First, prepare the data for the boxes:首先,为盒子准备数据:

# separate ColumnDataSource for boxes
boxes_data = pd.concat([
    q1.rename(columns={"score":"q1"}),
    q2.rename(columns={"score":"q2"}),
    q3.rename(columns={"score":"q3"}),
    iqr.rename(columns={"score":"iqr"})
], axis=1)

Next, in the portion of the code that draws the boxes, save the references to renderers so that the HoverTool only triggers on them and not figure-wide:接下来,在绘制框的部分代码中,保存对渲染器的引用,以便HoverTool仅在它们上触发而不是在图形范围内触发:

# boxes
boxes_source = ColumnDataSource(boxes_data)
top_box = p.vbar(
    "group", 0.7, "q2", "q3", fill_color="#E08E79",
    line_color="black", source=boxes_source)

bottom_box = p.vbar(
    "group", 0.7, "q1", "q2", fill_color="#3B8686",
    line_color="black", source=boxes_source)

# add hover just to the two box renderers
box_hover = HoverTool(renderers=[top_box, bottom_box],
                         tooltips=[
                             ('q1', '@q1'),
                             ('q2', '@q2'),
                             ('q3', '@q3'),
                             ('iqr', '@iqr')
                         ])
p.add_tools(box_hover)

The rest of the code is fine as is so the result is:其余的代码很好,结果是: 在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM