1. ホーム
  2. python

[解決済み] Bokeh HoverToolに"?"が表示される。

2022-02-08 13:06:38

質問

PythonでBokehライブラリに手を出しているのですが、ちょっと困っています。Bokehのチュートリアルサイトにある以下のようなコードを持っています。

from bokeh.plotting import figure 
from bokeh.io import output_notebook, show
output_notebook()
from bokeh.sampledata.autompg import autompg
from bokeh.models import HoverTool
from bokeh.plotting import ColumnDataSource

grouped = autompg.groupby("yr")
mpg2 = grouped["mpg"]
avg = mpg2.mean()
std = mpg2.std()
years = list(grouped.groups.keys())
american = autompg[autompg["origin"]==1]
japanese = autompg[autompg["origin"]==3]

p = figure(title="MPG by Year (Japan and US)")

p.vbar(x=years, bottom=avg-std, top=avg+std, width=0.8, 
       fill_alpha=0.2, line_color=None, legend="MPG 1 stddev")

p.circle(x=japanese["yr"], y=japanese["mpg"], size=10, alpha=0.5,
         color="red", legend="Japanese")

p.triangle(x=american["yr"], y=american["mpg"], size=10, alpha=0.3,
           color="blue", legend="American")

p.legend.location = "top_left"
show(p)

動作はするのですが、ポイントにカーソルを合わせると馬力が表示される機能を追加したいのです。試してみたのは

grouped = autompg.groupby("yr")
mpg = grouped["mpg"]
avg = mpg.mean()
std = mpg.std()
years = list(grouped.groups.keys())
american = autompg[autompg["origin"]==1]
japanese = autompg[autompg["origin"]==3]

source = ColumnDataSource(data=
   dict(autompg)
)

hover1 = HoverTool(tooltips=[("hp", "@hp")])


p = figure(title="MPG by Year (Japan and US)",tools=[hover1])

p.vbar(x=years, bottom=avg-std, top=avg+std, width=0.8, 
       fill_alpha=0.2, line_color=None, legend="MPG 1 stddev")

p.circle(x=japanese["yr"], y=japanese["mpg"], size=10, alpha=0.5,
         color="red", legend="Japanese")

p.triangle(x=american["yr"], y=american["mpg"], size=10, alpha=0.3,
           color="blue", legend="American")

p.legend.location = "top_left"
show(p)

そこで、それを実現するために期待したHoverToolを定義しました。残念ながら、それは "hp.を表示するだけです。と表示されるだけです。私はそれがデータソースの問題であると思うが、私はここで多くの経験を持っておらず、それを自分で把握することができない。dict()なしのソースを試してみたり、americanやjapaneseに設定してみたりしましたが、どれも違いはありませんでした。

ありがとうございました。

解決するには?

を渡す必要があります。 source をグリフ関数に渡し、座標の列名を参照します。リテラルなリスト/配列を(上でやっているように) circle などの場合、BokehはそのデータのCDSを隠蔽して作成しますが、グリフ関数に渡したデータだけ(つまりは なし hp"のような余分な列)。データの異なるサブセットに対して異なるグリフを描画しようとしているので、最も簡単なのは CDSView を使用して、クライアント上でそれらをグループ化します。代わりに以下のようなものがあります。

from bokeh.plotting import figure
from bokeh.io import show
from bokeh.sampledata.autompg import autompg
from bokeh.models import ColumnDataSource, CDSView, GroupFilter, HoverTool

p = figure()

# Bokeh factors must be strings
autompg.origin = [str(x) for x in autompg.origin]

source = ColumnDataSource(autompg)

# view for just japanese origin
japanese = CDSView(source=source, filters=[GroupFilter(column_name='origin', group="1")])

# draw circles for just the japanese view
p.circle(x="yr", y="mpg", size=10, alpha=0.5, color="red", legend="Japanese",
         source=source, view=japanese)

# view for just japanese origin
american = CDSView(source=source, filters=[GroupFilter(column_name='origin', group="3")])

# draw triangles for just the american view
p.triangle(x="yr", y="mpg", size=10, alpha=0.5, color="blue", legend="american",
         source=source, view=american)

p.add_tools(HoverTool(tooltips=[("hp", "@hp")]))

show(p)