import bokeh.colors
import pandas as pd
from bokeh.plotting import figure, show
import bokeh.models
import bokeh.palettes
import bokeh.transform
data = {
'date': ['2024-04-15', '2024-04-16', '2024-04-17' ],
'Bill': [1, 1, -1],
'Note': [1, -1, -1],
'Bond': [1, 0, -1]
}
df = pd.DataFrame(data)
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)
p = figure(sizing_mode='stretch_both', x_axis_type='datetime', x_axis_label='date', y_axis_label='change')
p.vbar_stack(stackers=['Bill', 'Note', 'Bond'], x='date', width=pd.Timedelta(days=0.9), color=bokeh.palettes.Category20[3], source=df, legend_label=['Bill', 'Note', 'Bond'])
p.legend.click_policy = 'hide'
show(p)
在第一列中,所有三个值都是正数,因此它们按预期向上堆叠。
在第三列中,所有三个值都是负数,因此它们按预期向下堆叠。
在中间一列中,我们有 1 个正值,因此它向上堆叠,然后我们有 1 个负值,因此它向下堆叠。结果是,我们最终得到了高度为 1 的堆栈的外观。
有没有办法让正值仅叠加在 y 轴的正侧,而负值仅显示在 y 轴的负侧?
换句话说,图表如下所示:
技巧是将 DataFrame 分为正数和负数,并绘制两个堆栈器。
这是代码:
p = figure(x_axis_type='datetime', x_axis_label='date', y_axis_label='change')
p.vbar_stack(
stackers=['Bill', 'Note', 'Bond'],
x='date', width=pd.Timedelta(days=0.9),
color=bokeh.palettes.Category20[3],
source=df[df<0].fillna(0),
legend_label=['Bill', 'Note', 'Bond'],
line_width=0,
)
p.vbar_stack(
stackers=['Bill', 'Note', 'Bond'],
x='date', width=pd.Timedelta(days=0.9),
color=bokeh.palettes.Category20[3],
source=df[df>0].fillna(0),
legend_label=['Bill', 'Note', 'Bond'],
line_width=0,
)
p.legend.click_policy = 'hide'
show(p)
用零填充选择很重要,以避免使用
np.nan
添加。我还添加了 line_width=0
,以避免栏两侧出现薄橙色框。
结果如下所示: