Reputation: 123
I have a multi line plot in Bokeh:
import pandas as pd
from bokeh.plotting import figure, show
from bokeh.palettes import Category20c_7
from bokeh.io import output_file
from bokeh.models import SingleIntervalTicker, LinearAxis, ColumnDataSource
output_file("conso_daily.html")
treatcriteria_daily_data = pd.read_csv("treatcriteria_evolution.csv", sep=';')
final_daily_data = treatcriteria_daily_data.groupby(['startdate_weekyear','startdate_dayweek'],as_index = False).sum().pivot('startdate_weekyear','startdate_dayweek').fillna(0)
# keep only integer values in x axis
def interval_integer(plot):
ticker = SingleIntervalTicker(interval=1, num_minor_ticks=1)
xaxis = LinearAxis(ticker=ticker)
plot.add_layout(xaxis, 'below')
numlines = len(final_daily_data.columns)
palette = Category20c_7[0:numlines]
# remove the last week if there is not all the data
data_without_last_week = final_daily_data[(final_daily_data != 0).all(1)]
cpu_values_daily = data_without_last_week.values.T.tolist()
weeks = []
for i in range(0,len(data_without_last_week.columns)):
weeks.append(data_without_last_week.index)
df = {'week': weeks,
'day': ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
'color': ['red', 'orange', 'yellow', 'green', 'grey', 'pink', 'purple'],
'HCPU': cpu_values_daily}
source = ColumnDataSource(df)
p = figure(width=800, height=500)
p.multi_line(xs='week', ys='HCPU', legend='day', color='color',
line_width=5, line_alpha=0.6, hover_line_alpha=1.0,
source=source)
p.xaxis.visible = False
p.left[0].formatter.use_scientific = False
interval_integer(p)
show(p)
I want to show legend outside the plot area because the top curve (Sunday) is hidden. I try to follow this thread, but it's for single lines and not for multiline: Create a two line legend in a bokeh plot
Using this code, I searched to show legend in right outside the plot area, but it doesn't work:
legend = Legend(items=[
('Monday', [p[0]]),
('Tuesday', [p[1]]),
('Wednesday', [p[2]]),
('Thursday', [p[3]]),
('Friday', [p[4]]),
('Saturday', [p[5]]),
('Sunday', [p[6]]),
], location=(0, -30))
p.add_layout(legend, 'right')
TypeError: 'Figure' object is not subscriptable
Thank you.
Edit: Here is my data 'final_daily_data' if it's useful:
mc_cpu_hours \
startdate_dayweek 1 2 3
startdate_weekyear
27 527644.000731 468053.338183 517548.838022
28 349896.850976 481313.693908 372385.568095
29 168595.113447 388117.184580 373894.548600
30 176007.786269 364379.872622 366155.953075
31 177517.591864 0.000000 0.000000
startdate_dayweek 4 5 6 7
startdate_weekyear
27 573669.325129 515710.534260 511711.421986 841073.028107
28 378069.713821 385937.231788 385856.666340 842468.209151
29 343235.942227 376405.876236 400007.946715 662019.708660
30 375948.240935 366151.336263 395790.387672 700936.336812
31 0.000000 0.000000 0.000000 686023.780120
Upvotes: 0
Views: 1134
Reputation: 23
Look at this answer, in particular the comment from @Sam De Meyer. In short, you create the figure, and then you do:
p.add_layout(p.legend[0], 'right')
show(p)
Upvotes: 0
Reputation: 6337
Your problem is in legend = Legend(items=[('Monday', [p[0]]), ...])
or even more precise in p[0]
, ..., p[7]
. The figure objet is not subscriptable, because it is not a list or dictionary and this raises the error. I think in your case it is enough to define the Legend()
-class blank, without any further information.
Small Example
import pandas as pd
from bokeh.plotting import figure, show, output_notebook
from bokeh.models import Legend
output_notebook()
source = pd.DataFrame({
'xs':[[1,2,3,4],[1,2,3,4]],
'ys':[[1,2,3,4],[4,3,2,1]],
'label':['a','b'],
'color':['blue','green']
})
p = figure(width=400, height=300)
p.add_layout(Legend(),'right')
p.multi_line(xs='xs', ys='ys', legend_field ='label', color='color', source=source)
show(p)
Output
Upvotes: 1