Я думаю, что эта проблема станет намного проще, если вы преобразуете свои данные в следующую форму:
from bokeh.plotting import figure
from bokeh.io import show
from bokeh.transform import stack, factor_cmap
import pandas as pd
df = pd.DataFrame({
"Category": ["a", "b"],
"Regime1_Value": [1, 4],
"Regime1_State": ["A", "B"],
"Regime2_Value": [2, 5],
"Regime2_State": ["B", "B"],
"Regime3_Value": [3, 6],
"Regime3_State": ["B", "A"]})
p = figure(x_range=["a", "b"])
p.vbar_stack(["Regime1_Value", "Regime2_Value", "Regime3_Value"],
x="Category",
fill_color=[
factor_cmap(state, palette=["red", "green"], factors=["A", "B"])
for state in ["Regime1_State","Regime2_State", "Regime3_State"]],
line_color="black",
width=0.9,
source=df)
show(p)
Это немного странно, потому что vbar_stack
ведет себя не так, как "обычный глиф".Обычно у вас есть три варианта атрибутов средства визуализации (предположим, что мы хотим построить n точек / прямоугольников / фигур / вещей:
- . Приведите одно значение, которое используется для всех n глифов
- Дайте массив длины n данных
Ноvbar_stack
не создает одного средства визуализации, оно создает столько элементов, сколько есть элементов в первом массиве, который вы даете. Позволяет назвать это число к. Затем, чтобы понять атрибуты, у вас снова есть три варианта:
- Дайте одно значение, которое используется для всех глифов
- Дайте массив из k вещей, которые используются в качестве имен столбцов в источнике (каждый поиск должен создать массив длины n).
- Дайте массив длины n данных (так что для всех 1-k глифов есть одинаковые данные).
Так что p.vbar(x=[a,b,c])
и p.vbar_stacked(x=[a,b,c])
на самом деле делают разные вещи (первый дает буквальные данные, второй дает имена столбцов), который перепутали это не ясно из документации.
Но почему мы должны так странно преобразовывать ваши данные?Развернем vbar_stack
и напишем его самостоятельно (подробности опущены для краткости):
plotted_regimes = []
для режима в режимах: если нет plotted_regimes: bottom = 0 else: bottom= stack (* plotted_regimes) p.vbar (bottom = bottom, top = stack (* plotted_regimes, mode)) plotted_regimes.append (mode)
Таким образом, для каждого режима у нас есть отдельный vbar, у которого есть дно, гдесумма других режимов закончилась.Теперь с исходной структурой данных это на самом деле невозможно, потому что не нужно иметь значение для каждого режима для каждой категории.Здесь мы вынуждены установить эти значения равными 0, если мы действительно хотим.
Поскольку уложенные значения соответствуют именам столбцов, мы должны поместить эти значения в один кадр данных.Вызов vbar_stack
в начале также может быть записан с помощью stack
(в основном потому, что vbar_stack
- это удобная оболочка для stack
).
factor_cmap
используется, чтобы мы неприходится вручную назначать цвета.Мы также могли бы просто добавить столбец Regime1_Color
, но таким образом сопоставление выполняется автоматически (и на стороне клиента).