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

Plotly分组条形图:分面子图中条形X轴对齐异常问题求助

解决Plotly分组条形图子组数量不同的对齐与间隙问题

一、Plotly Express 偏移问题解决

问题核心是Plotly Express会基于全局所有ID生成分组位置,导致子组少的分面出现空白占位。可通过自定义偏移量结合offsetgroup和alignmentgroup让每个分面内的条形居中对齐:

import pandas as pd
import plotly.express as px

data = {'Facet':['A','A','B','B','B','B'],'ID':['01','01','02','02','03','03'],'Day':[0,3,0,3,0,3],'Val':[98,99,97,95,98,99]}
df = pd.DataFrame(data=data)

# 统计每个Facet+Day组合下的ID数量,用于计算偏移
df['group_count'] = df.groupby(['Facet', 'Day'])['ID'].transform('nunique')

fig = px.bar(df, x='Day', y='Val', color='ID', facet_col='Facet')

# 遍历每个trace,设置偏移量和对齐组
for trace in fig.data:
    # 获取当前trace对应的Facet和Day
    facet = trace.marker.color.split('=')[1].split(',')[0]
    day = int(trace.x[0])
    # 获取该组合下的分组数量
    group_count = df[(df['Facet']==facet) & (df['Day']==day)]['group_count'].iloc[0]
    # 计算偏移:让同Day下的条形居中排列
    id_idx = df[df['ID']==trace.name].index[0] % group_count
    trace.offsetgroup = f"{facet}_{day}"
    trace.alignmentgroup = f"{facet}_{day}"
    trace.offset = -(group_count-1)*0.4 + id_idx*0.8

# 移除空白占位的X轴无效标签
fig.update_xaxes(categoryorder='array', categoryarray=[0,3])
fig.update_layout(barmode='group', bargroupgap=0)
fig.show()

二、plotly.graph_objects 间隙问题解决

固定条形宽度会导致分组数不同时出现间隙,解决方案是根据每个子图的分组数量动态计算条形宽度,确保同一Day下的条形紧密排列且居中:

import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots

data = {'Facet':['A','A','B','B','B','B'],'ID':['01','01','02','02','03','03'],'Day':[0,3,0,3,0,3],'Val':[98,99,97,95,98,99]}
df = pd.DataFrame(data=data)

grouped = df.groupby('Facet', sort=False)
fig2 = make_subplots(rows=1, cols=grouped.ngroups, subplot_titles=list(grouped.groups.keys()))

for i, (name, group) in enumerate(grouped):
    # 获取当前Facet下的唯一ID数量
    id_count = group['ID'].nunique()
    # 计算每个条形的宽度:总宽度占X轴刻度的0.8,平分给每个分组
    bar_width = 0.8 / id_count
    # 遍历每个ID子组
    for idx, (subname, subgroup) in enumerate(group.groupby('ID')):
        # 计算偏移量,让分组居中
        offset = -(id_count-1)*bar_width/2 + idx*bar_width
        fig2.add_trace(
            go.Bar(
                x=subgroup['Day'],
                y=subgroup['Val'],
                name=subname,
                width=bar_width,
                offsetgroup=f"{name}_{subgroup['Day'].iloc[0]}",
                alignmentgroup=f"{name}_{subgroup['Day'].iloc[0]}",
                offset=offset
            ),
            row=1, col=i+1
        )
    # 固定当前子图的X轴刻度
    fig2.update_xaxes(categoryarray=[0,3], row=1, col=i+1)

fig2.update_layout(barmode='group', bargroupgap=0, showlegend=True)
fig2.show()

关键思路总结

  • 对齐问题:通过alignmentgroup确保同一Day下的条形属于同一对齐组,用offsetgroup隔离不同Facet的分组,再根据分组数量计算偏移量实现居中。
  • 间隙问题:动态计算条形宽度,避免固定宽度导致的适配问题,让每个分组的条形紧密排列且占满X轴刻度的合理范围。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 22:20:30