добавить всплывающую подсказку к линейному графику в боке, созданный с помощью цикла - PullRequest
0 голосов
/ 18 января 2019

Я сделал график боке, используя цикл for. Но этот метод не позволяет мне добавлять всплывающие подсказки, так как использование метода @ для кортежа при наведении не позволяет мне добавлять имя столбца, если это цикл. Есть ли способ добавить значение и название каждой страны к моей подсказке в цикле for? # строка наведения ниже не работает.

import pandas as pd
url = 'https://www.bp.com/content/dam/bp/business-sites/en/global/corporate/xlsx/energy-economics/statistical-review/bp-stats-review-2018-all-data.xlsx'
df = pd.read_excel(url, sheet_name = 'Gas Consumption - Bcf', skiprows = 2, skipfooter = 15)
df = df.dropna(how='all').transpose()
df = df.rename(columns=df.iloc[0]).drop(df.index[0])
df = df.reset_index()
df.rename(columns = {'index': 'Year'}, inplace=True)
df = df.drop(df.index[[53, 54, 55]])
df['Year'] = pd.to_datetime(df['Year'], format = '%Y')

top_ten = df.tail(1).T.reset_index().iloc[1:,:]
top_ten.columns = ['country', 'value']
top_ten = top_ten.sort_values(by = 'value', ascending= False)
top_ten_list = top_ten['country'].tolist()
top_ten_list = [x for x in top_ten_list if not 'Total' in x][0:10]

from bokeh.plotting import figure, output_notebook, show, reset_output
from bokeh.models import ColumnDataSource
from bokeh.palettes import Category10
from bokeh.models import HoverTool
import itertools
from bokeh.models import Legend

mypalette = Category10[10]
output_notebook()

q = figure(plot_width=700, plot_height=500, x_axis_type='datetime')

for c, color in zip(top_ten_list, mypalette):
    q.line(df['Year'],df[c], legend=c, color = color, line_width = 3)
    #hover = HoverTool(tooltips = [('Date', '@Year{%Y}'), ('Country', '@c billion cubic feet per day')], formatters = {'Year' : 'datetime'})

q.add_tools(hover)
q.legend.location = "top_left"
q.xaxis.axis_label = "Date"
q.yaxis.axis_label = "billion cubic feet per day"
q.legend.click_policy="hide"
show(q)

1 Ответ

0 голосов
/ 18 января 2019

Я заменил цикл for на ColumnDataSource и multiline, что облегчает добавление hovertool. Мне также пришлось добавить несколько CustomJS, потому что вызов @ x / @ y из многострочного показывает все значения x / y. CustomJS гарантирует, что он показывает только правильную позицию x / y.

import pandas as pd
from bokeh.plotting import figure, show, reset_output, output_notebook
from bokeh.models import ColumnDataSource
from bokeh.palettes import Category10
from bokeh.models import HoverTool, ColumnDataSource
from bokeh.models.glyphs import MultiLine
import itertools
from bokeh.models import Legend
from bokeh.models.tools import CustomJSHover

url = 'https://www.bp.com/content/dam/bp/business-sites/en/global/corporate/xlsx/energy-economics/statistical-review/bp-stats-review-2018-all-data.xlsx'
df = pd.read_excel(url, sheet_name = 'Gas Consumption - Bcf', skiprows = 2, skipfooter = 15)
df = df.dropna(how='all').transpose()
df = df.rename(columns=df.iloc[0]).drop(df.index[0])
df = df.reset_index()
df.rename(columns = {'index': 'Year'}, inplace=True)
df = df.drop(df.index[[53, 54, 55]])

top_ten = df.tail(1).T.reset_index().iloc[1:,:]
top_ten.columns = ['country', 'value']
top_ten = top_ten[~top_ten.country.str.contains("Total")]
top_ten = top_ten.sort_values(by = 'value', ascending= False)
top_ten_list = top_ten['country'].tolist()[:10]
top_ten = df[top_ten_list]

y = [df[country].tolist() for country in top_ten.columns.tolist()]
x, xLst = [], df['Year'].tolist()
for i in range(10):
    x.append(xLst)

x_custom = CustomJSHover(code="""
    return '' + special_vars.data_x
""")

y_custom = CustomJSHover(code="""
    return '' + special_vars.data_y
""")

data = {'x': x, 'y': y, 'color': Category10[10], 'name': top_ten_list}

source = ColumnDataSource(data)

output_notebook()

q = figure(plot_width=700, plot_height=500)

q.multi_line(xs='x', ys='y', line_color='color', legend='name', line_width = 3, source=source)
q.add_tools(HoverTool(
    tooltips=[
    ('Year', '@x{custom}'),
    ('Value', '@y{custom}'),
    ('Country', '@name')],
    formatters=dict(x=x_custom, y=y_custom)
))

q.legend.location = "top_left"
q.xaxis.axis_label = "Date"
q.yaxis.axis_label = "billion cubic feet per day"
q.legend.click_policy="hide"
show(q)
...