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()
问题原因
- Y轴定义缺失:循环中使用
y{i+1}为每个行为类型分配独立Y轴(i从0到3,对应y1、y2、y3、y4),但layout仅定义了yaxis(即y1)和yaxis2,y3、y4未定义,导致对应trace无法渲染显示。 - 偏移量逻辑错误:原代码中
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()
修复说明
- 补充Y轴定义:在layout中添加
yaxis3和yaxis4,确保每个行为类型对应的Y轴都存在,且全部匹配主Y轴的范围,保证堆叠高度统一。 - 修正偏移量逻辑:将偏移量和宽度改为基于x轴类别的相对值,使各组条形在x轴刻度两侧均匀分布,避免被移出可视区域。
- 统一Y轴范围:提前计算所有分组的最大堆叠高度,确保所有Y轴使用相同范围,保证图表展示效果一致。
内容的提问来源于stack exchange,提问作者Zachary Kondak
相关产品推荐
相关产品推荐

