python bokeh - 堆叠条形图,分组和堆叠的分类数据,n 个堆叠系列的案例

python bokeh - stacked bar, categorical data grouped and stacked, case for n stacked series

我正在尝试在散景中为散景文档中提供的分类数据重现堆叠的 abd 分组条形图 here: https://docs.bokeh.org/en/latest/docs/user_guide/categorical.html#stacked-and-grouped) 我想沿着 x 轴 'day' 和 'category' 获得两个分类级别。 我尝试重现 n 系列的图表。

我收到一个我不明白的错误。我的输入数据似乎与 bokeh 文档中的示例具有相同的格式,除了我想考虑包含值的 n 列(我在示例中提供了 3,但我希望代码真正适用于 n 列)。

是否可以堆叠超过 2 个系列?
为什么我的代码不工作?
有没有更有效的方法来做到这一点?

我的代码:

import pandas as pd
import bokeh.io
from bokeh.io import output_file, show
from bokeh.models import ColumnDataSource, FactorRange
from bokeh.plotting import figure

data = [['Mon', '1' , 1.1 , 1.2 , 1.3 ], 
        ['Mon', '2' , 2.1 , 2.2 , 2.3 ], 
        ['Mon', '3' , 3.1 , 3.2 , 3.3 ], 
        ['Tue', '1' , 4.1 , 4.2 , 4.3 ],
        ['Tue', '2' , 5.1,  5.2 , 5.3 ], 
        ['Tue', '3' , 6.1 , 6.2 , 6.3 ]] 

df = pd.DataFrame(data, columns = ['day', 'category','col_1','col_2','col_3']) 

factors = list(df[['day','cat']].to_records(index=False))
factors_dict = {'x':factors}

series = list(df.columns)[2:]
series_dict =  df.iloc[:,2:].to_dict('l')

data_dict = {**factors_dict,**series_dict}
source = ColumnDataSource(data_dict)


p = figure(x_range=FactorRange(*factors), plot_height=250,
           toolbar_location=None, tools="")


p.vbar_stack(series, x='x', width=0.9, alpha=0.5, color=["blue", "red", "green"], source=source,
             legend_label=series)

p.y_range.start = 0
p.y_range.end = 18
p.x_range.range_padding = 0.1
p.xaxis.major_label_orientation = 1
p.xgrid.grid_line_color = None
p.legend.location = "top_center"
p.legend.orientation = "horizontal"

show(p)

错误

ValueError: expected an element of either Seq(String), Seq(Tuple(String, String)) or Seq(Tuple(String, String, String)), 
got [('Mon', '1'), ('Mon', '2'), ('Mon', '3'), ('Tue', '1'), ('Tue', '2'), ('Tue', '3')]

散景文档示例中的因素

[('Q1', 'jan'),
 ('Q1', 'feb'),
 ('Q1', 'mar'),
 ('Q2', 'apr'),
 ('Q2', 'may'),
 ('Q2', 'jun'),
 ('Q3', 'jul'),
 ('Q3', 'aug'),
 ('Q3', 'sep'),
 ('Q4', 'oct'),
 ('Q4', 'nov'),
 ('Q4', 'dec')]

我的代码中的因素

[('Mon', '1'),
 ('Mon', '2'),
 ('Mon', '3'),
 ('Tue', '1'),
 ('Tue', '2'),
 ('Tue', '3')]

我传递给 x_range 的因素与 bokeh 文档中提供的示例具有相同的形式,但是当我将它们传递给 x_range 时出现错误。

ColumnDataSource 好像也一样

 {'x':  [('Q1', 'jan'), ('Q1', 'feb'), ('Q1', 'mar'), 
         ('Q2', 'apr'), ('Q2', 'may'), ('Q2', 'jun'), 
         ('Q3', 'jul'), ('Q3', 'aug'), ('Q3', 'sep'), 
         ('Q4', 'oct'), ('Q4', 'nov'), ('Q4', 'dec')], 
 'east': [5, 5, 6, 5, 5, 4, 5, 6, 7, 8, 6, 9], 
 'west': [5, 7, 9, 4, 5, 4, 7, 7, 7, 6, 6, 7]}

在我的例子中

{'x': [('Mon', '1'), ('Mon', '2'), ('Mon', '3'), 
        ('Tue', '1'), ('Tue', '2'), ('Tue', '3')], 
 'col_1': [1.1, 2.1, 3.1, 4.1, 5.1, 6.1], 
 'col_2': [1.2, 2.2, 3.2, 4.2, 5.2, 6.2], 
 'col_3': [1.3, 2.3, 3.3, 4.3, 5.3, 6.3]}

这里的问题是您的 factors 值不是 2 元组字符串的列表。由于您从 DataFrame 构造它的方式,它实际上是一个 numpy 记录列表:

>>> type(factors[0])
numpy.record

Bokeh 不知道该怎么办。提出功能请求以查看是否有任何方法可以更好地处理这种特定情况可能是合理的。但与此同时,您只需将数据转换为 Bokeh 期望的格式。可能有几种方法可以做到这一点,这里是一个:

factors = [tuple(x) for x in factors]