You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python Bokeh绘制堆叠条形图遇vbar_stack属性错误求助

Fixing the Bokeh Stacked Vertical Bar Chart Error

Hey there! Let's get that stacked bar chart working for you. The error you're seeing—AttributeError: 'Figure' object has no attribute 'vbar_stack'—happens because Bokeh doesn't have a vbar_stack method for vertical stacked bars. Instead, we need to adjust how we structure our data and use Bokeh's built-in tools to create the stacked effect.

Step 1: Correctly Structure Your Data

First, let's clean up the data aggregation to get a wide-format DataFrame where each class has separate columns for "yes" and "no" counts. This makes it easier to build stacked bars in Bokeh:

import pandas as pd
from bokeh.plotting import figure, show, ColumnDataSource
from bokeh.models import LabelSet
from bokeh.palettes import Viridis2

# Your raw data
raw_data = {
    'Class': ['S', 'S', 'G', 'P', 'P', 'V', 'G', 'V', 'V', 'V', 'P'],
    'Class_Change': ['yes', 'yes', 'yes', 'yes', 'yes', 'no', 'yes', 'no', 'no', 'yes', 'no']
}
df_class = pd.DataFrame(raw_data)

# Aggregate counts and pivot to wide format
df_counts = df_class.groupby(['Class', 'Class_Change']).size().unstack(fill_value=0)

This gives us a structured DataFrame like this:

Classnoyes
G02
P12
S02
V31

Step 2: Build the Stacked Bar Chart

Now we'll create a ColumnDataSource with our wide-format data, then add two vertical bar layers (one for "no", one for "yes")—using the bottom parameter for the second layer to stack it on top of the first:

# Create data source
source = ColumnDataSource(data={
    'Classes': df_counts.index.tolist(),
    'no_counts': df_counts['no'].tolist(),
    'yes_counts': df_counts['yes'].tolist(),
    'colors': Viridis2  # Colors for "no" and "yes" segments
})

# Initialize the plot
plot = figure(
    x_range=df_counts.index.tolist(),
    y_range=(0, df_counts.sum(axis=1).max() + 0.5),  # Add buffer for labels
    plot_height=350,
    plot_width=800,
    title="Class Change Status Counts",
    toolbar_location=None,
    tools=""
)

# Add "no" bars (bottom layer)
no_bars = plot.vbar(
    x='Classes',
    top='no_counts',
    width=0.9,
    color='colors[0]',
    source=source,
    legend_label='No'
)

# Add "yes" bars (stacked on top of "no")
yes_bars = plot.vbar(
    x='Classes',
    top='yes_counts',
    bottom='no_counts',
    width=0.9,
    color='colors[1]',
    source=source,
    legend_label='Yes'
)

# Add count labels to each bar segment
# Labels for "no" bars
no_labels = LabelSet(
    x='Classes',
    y='no_counts',
    text='no_counts',
    level='glyph',
    y_offset=-15,  # Adjust position for readability
    source=source,
    render_mode='canvas'
)

# Labels for "yes" bars (positioned above the "no" bars)
yes_labels = LabelSet(
    x='Classes',
    y='no_counts',
    text='yes_counts',
    level='glyph',
    y_offset=15,
    source=source,
    render_mode='canvas'
)

plot.add_layout(no_labels)
plot.add_layout(yes_labels)

# Clean up plot styling
plot.legend.title = "Change Status"
plot.xaxis.axis_label = "Class"
plot.yaxis.axis_label = "Count"
plot.legend.location = "top_left"

# Show the chart
show(plot)

Key Fixes Explained:

  1. Data Format: We converted the grouped data to a wide format so each status ("yes"/"no") has its own column—this is essential for stacking in Bokeh.
  2. Stacking Logic: Instead of a non-existent vbar_stack method, we use two vbar calls: the second uses bottom='no_counts' to sit on top of the first layer.
  3. Label Placement: We added separate labels for each bar segment, adjusting their position to be readable without overlapping.

内容的提问来源于stack exchange,提问作者Shuvayan Das

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:10:42