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

Python Plotly分组堆叠条形图仅显示SIB数据问题求助

分组堆叠条形图仅显示最后一组数据的问题排查与修复

问题背景

尝试创建按时长区间堆叠、按行为类型分组的分组堆叠条形图,参考分组堆叠条形图的实现方案后,使用自有数据集运行代码时,仅显示最后一个变量“SIB”的数据,其余行为类型的数据未在图表中呈现,确认数据结构与示例一致,怀疑循环逻辑存在问题。

原代码如下:

df = pd.read_pickle("data_save")

print(df.head())

# Create a figure with the right layout
fig = go.Figure(
    layout=go.Layout(
        height=600,
        width=1000,
        barmode="relative",
        yaxis_showticklabels=False,
        yaxis_showgrid=False,
        yaxis_range=[0, df.groupby(axis=1, level=0).sum().max().max()],
       # Secondary y-axis overlayed on the primary one and not visible
        yaxis2=go.layout.YAxis(
            visible=False,
            matches="y",
            overlaying="y",
            anchor="x",
        ),
        font=dict(size=24),
        legend_x=0,
        legend_y=1,
        legend_orientation="h",
        hovermode="x",
        margin=dict(b=0,t=10,l=0,r=10)
    )
)

# Define some colors for the product, revenue pairs
colors = {
    "Aggression" : {
        "Duration: 0" : "#F7FF00",
        "Duration: 11-15": "#D6DD00",
        "Duration: 16-20": "#BAC100",
        "Duration: 20+": "#9CA200",
        "Duration: 6-10": "#838800",
        "Duration: <5": "#6A6E00",
    },
    "Disruptive" : {
        "Duration: 0" : "#00FF08",
        "Duration: 11-15": "#00ED07",
        "Duration: 16-20": "#00D006",
        "Duration: 20+": "#00AD05",
        "Duration: 6-10": "#008C04",
        "Duration: <5": "#006A03",
    },
    "SIB" : {
        "Duration: 0" : "#00D8FF",
        "Duration: 11-15": "#00BCDE",
        "Duration: 16-20": "#00A7C6",
        "Duration: 20+": "#0089A3",
        "Duration: 6-10": "#006D82",
        "Duration: <5": "#005262",
    },
    "Self Mutilation" : {
        "Duration: 0" : "#FF0000",
        "Duration: 11-15": "#F00202",
        "Duration: 16-20": "#CA0000",
        "Duration: 20+": "#AF0000",
        "Duration: 6-10": "#900000",
        "Duration: <5": "#6C0000",
    },
}

# Add the traces
for i, t in enumerate(colors):
    for j, col in enumerate(df[t].columns):
        if (df[t][col] == 0).all():
            continue
        fig.add_bar(
            x=df.index,
            y=df[t][col],
            # Set the right yaxis depending on the selected product (from enumerate)
            yaxis=f"y{i + 1}",
            # Offset the bar trace, offset needs to match the width
            # The values here are in milliseconds, 1billion ms is ~1/3 month
            offsetgroup=str(i),
            offset=(i - 1) * 1000000000,
            width=100000000,
            legendgroup=t,
            legendgrouptitle_text=t,
            name=col,
            marker_color=colors[t][col],
            marker_line=dict(width=2, color="#333"),
            hovertemplate="%{y}<extra></extra>"
        )

fig.show()

问题原因

  1. Y轴定义缺失:循环中使用y{i+1}为每个行为类型分配独立Y轴(i从0到3,对应y1、y2、y3、y4),但layout仅定义了yaxis(即y1)和yaxis2,y3、y4未定义,导致对应trace无法渲染显示。
  2. 偏移量逻辑错误:原代码中offset=(i - 1) * 1000000000的偏移量数值过大,结合width=100000000的设置,导致前几组条形被移出可视区域,仅最后一组SIB的条形落在可见范围内。

修复后的代码

import pandas as pd
import plotly.graph_objects as go

df = pd.read_pickle("data_save")

print(df.head())

# 统一计算最大Y值,保证所有分组堆叠高度一致
max_y = df.groupby(axis=1, level=0).sum().max().max()

fig = go.Figure(
    layout=go.Layout(
        height=600,
        width=1000,
        barmode="relative",
        yaxis_showticklabels=False,
        yaxis_showgrid=False,
        # 为每个行为类型定义匹配主Y轴的隐藏Y轴
        yaxis=go.layout.YAxis(visible=False, range=[0, max_y]),
        yaxis2=go.layout.YAxis(visible=False, matches="y", overlaying="y", anchor="x"),
        yaxis3=go.layout.YAxis(visible=False, matches="y", overlaying="y", anchor="x"),
        yaxis4=go.layout.YAxis(visible=False, matches="y", overlaying="y", anchor="x"),
        font=dict(size=24),
        legend_x=0,
        legend_y=1,
        legend_orientation="h",
        hovermode="x",
        margin=dict(b=0,t=10,l=0,r=10)
    )
)

colors = {
    "Aggression" : {
        "Duration: 0" : "#F7FF00",
        "Duration: 11-15": "#D6DD00",
        "Duration: 16-20": "#BAC100",
        "Duration: 20+": "#9CA200",
        "Duration: 6-10": "#838800",
        "Duration: <5": "#6A6E00",
    },
    "Disruptive" : {
        "Duration: 0" : "#00FF08",
        "Duration: 11-15": "#00ED07",
        "Duration: 16-20": "#00D006",
        "Duration: 20+": "#00AD05",
        "Duration: 6-10": "#008C04",
        "Duration: <5": "#006A03",
    },
    "SIB" : {
        "Duration: 0" : "#00D8FF",
        "Duration: 11-15": "#00BCDE",
        "Duration: 16-20": "#00A7C6",
        "Duration: 20+": "#0089A3",
        "Duration: 6-10": "#006D82",
        "Duration: <5": "#005262",
    },
    "Self Mutilation" : {
        "Duration: 0" : "#FF0000",
        "Duration: 11-15": "#F00202",
        "Duration: 16-20": "#CA0000",
        "Duration: 20+": "#AF0000",
        "Duration: 6-10": "#900000",
        "Duration: <5": "#6C0000",
    },
}

group_count = len(colors)
bar_width = 0.2  # 基于x轴为类别型的相对宽度,可根据需求调整

for i, t in enumerate(colors):
    for j, col in enumerate(df[t].columns):
        if (df[t][col] == 0).all():
            continue
        fig.add_bar(
            x=df.index,
            y=df[t][col],
            yaxis=f"y{i + 1}",
            offsetgroup=str(i),
            # 调整偏移量,使各组条形在x轴刻度旁均匀分布
            offset=(i - (group_count-1)/2) * bar_width,
            width=bar_width,
            legendgroup=t,
            legendgrouptitle_text=t,
            name=col,
            marker_color=colors[t][col],
            marker_line=dict(width=2, color="#333"),
            hovertemplate="%{y}<extra></extra>"
        )

fig.show()

修复说明

  1. 补充Y轴定义:在layout中添加yaxis3和yaxis4,确保每个行为类型对应的Y轴都存在,且全部匹配主Y轴的范围,保证堆叠高度统一。
  2. 修正偏移量逻辑:将偏移量和宽度改为基于x轴类别的相对值,使各组条形在x轴刻度两侧均匀分布,避免被移出可视区域。
  3. 统一Y轴范围:提前计算所有分组的最大堆叠高度,确保所有Y轴使用相同范围,保证图表展示效果一致。

内容的提问来源于stack exchange,提问作者Zachary Kondak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 08:44:56