web-dev-qa-db-fra.com

Dans Bokeh, comment ajouter des info-bulles à un graphique de séries chronologiques (outil de survol)?

Est-il possible d'ajouter des info-bulles à un graphique Timeseries?

Dans l'exemple de code simplifié ci-dessous, je veux voir un nom de colonne unique ("a", "b" ou "c") lorsque la souris survole la ligne appropriée.

Au lieu de cela, un "???" est affiché et les trois lignes obtiennent une info-bulle (plutôt que juste celle que je survole)

enter image description here

Selon la documentation ( http://bokeh.pydata.org/en/latest/docs/user_guide/tools.html#hovertool ), les noms de champ commençant par "@" sont interprétés comme des colonnes sur les données la source.

  1. Comment puis-je afficher les "colonnes" d'une trame de données pandas dans l'info-bulle?

  2. Ou, si l'interface TimeSeries de haut niveau ne prend pas en charge cela, des indices pour utiliser les interfaces de niveau inférieur pour faire la même chose? (ligne? multi_ligne?) ou convertir le DataFrame dans un format différent (ColumnDataSource?)

  3. Pour le crédit bonus, comment le "$ x" doit-il être formaté pour afficher la date comme une date?

merci d'avance

    import pandas as pd
    import numpy as np
    from bokeh.charts import TimeSeries
    from bokeh.models import HoverTool
    from bokeh.plotting import show

    toy_df = pd.DataFrame(data=np.random.Rand(5,3), columns = ('a', 'b' ,'c'), index = pd.DatetimeIndex(start='01-01-2015',periods=5, freq='d'))   

    p = TimeSeries(toy_df, tools='hover')  

    hover = p.select(dict(type=HoverTool))
    hover.tooltips = [
        ("Series", "@columns"),
        ("Date", "$x"),
        ("Value", "$y"),
        ]

    show(p)
30
bs123

Voici ce que j'ai trouvé.

Ce n'est pas joli mais ça marche.

Je suis encore nouveau sur Bokeh (Python d'ailleurs) donc si quelqu'un veut suggérer une meilleure façon de le faire, n'hésitez pas.

enter image description here

import pandas as pd
import numpy as np
from bokeh.charts import TimeSeries
from bokeh.models import HoverTool
from bokeh.plotting import show

toy_df = pd.DataFrame(data=np.random.Rand(5,3), columns = ('a', 'b' ,'c'), index = pd.DatetimeIndex(start='01-01-2015',periods=5, freq='d'))       

 _tools_to_show = 'box_zoom,pan,save,hover,resize,reset,tap,wheel_zoom'        

p = figure(width=1200, height=900, x_axis_type="datetime", tools=_tools_to_show)


# FIRST plot ALL lines (This is a hack to get it working, why can't i pass in a dataframe to multi_line?)   
# It's not pretty but it works. 
# what I want to do!: p.multi_line(df)
ts_list_of_list = []
for i in range(0,len(toy_df.columns)):
    ts_list_of_list.append(toy_df.index.T)

vals_list_of_list = toy_df.values.T.tolist()

# Define colors because otherwise multi_line will use blue for all lines...
cols_to_use =  ['Black', 'Red', 'Lime']
p.multi_line(ts_list_of_list, vals_list_of_list, line_color=cols_to_use)


# THEN put  scatter one at a time on top of each one to get tool tips (HACK! lines with tooltips not yet supported by Bokeh?) 
for (name, series) in toy_df.iteritems():
    # need to repmat the name to be same dimension as index
    name_for_display = np.tile(name, [len(toy_df.index),1])

    source = ColumnDataSource({'x': toy_df.index, 'y': series.values, 'series_name': name_for_display, 'Date': toy_df.index.format()})
    # trouble formating x as datestring, so pre-formating and using an extra column. It's not pretty but it works.

    p.scatter('x', 'y', source = source, fill_alpha=0, line_alpha=0.3, line_color="grey")     

    hover = p.select(dict(type=HoverTool))
    hover.tooltips = [("Series", "@series_name"), ("Date", "@Date"),  ("Value", "@y{0.00%}"),]
    hover.mode = 'mouse'

show(p)
14
bs123

Je ne connais pas les Pandas , J'utilise juste la liste python pour montrer l'exemple même de la façon d'ajouter des info-bulles à muti_lines, d'afficher les noms de séries et d'afficher correctement la date/l'heure) Voici le résultat . Merci à réponse de @ bs12 et réponse de @ tterry in Bokeh Plotting: n'activez les info-bulles que pour certains glyphes

mon résultat

# -*- coding: utf-8 -*-

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

dateX_str = ['2016-11-14','2016-11-15','2016-11-16']
#conver the string of datetime to python  datetime object
dateX = [datetime.strptime(i, "%Y-%m-%d") for i in dateX_str]

v1= [10,13,5]
v2 = [8,4,14]
v3= [14,9,6]
v = [v1,v2,v3]

names = ['v1','v2','v3']
colors = ['red','blue','yellow']

output_file('example.html',title = 'example of add tooltips to multi_timeseries')
tools_to_show = 'hover,box_zoom,pan,save,resize,reset,wheel_zoom'
p = figure(x_axis_type="datetime", tools=tools_to_show)

#to show the tooltip for multi_lines,you need use the ColumnDataSource which define the data source of glyph
#the key is to use the same column name for each data source of the glyph
#so you don't have to add tooltip for each glyph,the tooltip is added to the figure

#plot each timeseries line glyph
for i in xrange(3):
# bokeh can't show datetime object in tooltip properly,so we use string instead
    source = ColumnDataSource(data={
                'dateX': dateX, # python datetime object as X axis
                'v': v[i],
                'dateX_str': dateX_str, #string of datetime for display in tooltip
                'name': [names[i] for n in xrange(3)]
            })
    p.line('dateX', 'v',source=source,legend=names[i],color = colors[i])
    circle = p.circle('dateX', 'v',source=source, fill_color="white", size=8, legend=names[i],color = colors[i])

    #to avoid some strange behavior(as shown in the picture at the end), only add the circle glyph to the renders of hover tool
    #so tooltip only takes effect on circle glyph
    p.tools[0].renderers.append(circle)

# show the tooltip
hover = p.select(dict(type=HoverTool))
hover.tooltips = [("value", "@v"), ("name", "@name"), ("date", "@dateX_str")]
hover.mode = 'mouse'
show(p)

info-bulles avec un comportement étrange, deux conseils affichés en même temps

6
能豆子

Voici ma solution. J'ai inspecté la source de données de rendu du glyphe pour voir quels en sont les noms. Ensuite, j'utilise ces noms sur les info-bulles de l'aspirateur. Vous pouvez voir le graphique résultant ici .

import numpy as np
from bokeh.charts import TimeSeries
from bokeh.models import HoverTool
from bokeh.plotting import show

toy_df = pd.DataFrame(data=np.random.Rand(5,3), columns = ('a', 'b' ,'c'), index = pd.DatetimeIndex(start='01-01-2015',periods=5, freq='d'))   
#Bockeh display dates as numbers so convert to string tu show correctly
toy_df.index = toy_df.index.astype(str) 
p = TimeSeries(toy_df, tools='hover')  

#Next 3 lines are to inspect how are names on gliph to call them with @name on hover
#glyph_renderers = p.select(dict(type=GlyphRenderer))
#bar_source = glyph_renderers[0].data_source
#print(bar_source.data)  #Here we can inspect names to call on hover


hover = p.select(dict(type=HoverTool))
hover.tooltips = [
        ("Series", "@series"),
        ("Date", "@x_values"),
        ("Value", "@y_values"),
        ]

show(p)
2
josale