散景:多折线图中的图例外图

Bokeh: Legend outside plot in multi line chart

我在 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)

我想在绘图区域外显示图例,因为顶部曲线(星期日)被隐藏了。 我尝试关注此线程,但它适用于单行而不适用于多行:

使用此代码,我搜索以在绘图区域外显示图例,但它不起作用:

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

谢谢。

编辑:这是我的数据'final_daily_data'如果有用的话:

                     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

您的问题在 legend = Legend(items=[('Monday', [p[0]]), ...]) 中,或者更精确地在 p[0],...,p[7] 中。图形对象不可订阅,因为它不是列表或字典,这会引发错误。我认为在你的情况下定义 Legend()-class 空白就足够了,没有任何进一步的信息。

小例子

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)

输出