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

Plotly多行长图例布局问题:legend2无法使图表占满宽度

Plotly图例布局优化:分栏底部排列+图表占满宽度

问题背景

制作Plotly折线图时,因图例数量多、文本过长,自动图例布局无法满足需求。尝试通过legend2将图例分为两组放置在底部,但未能实现图表占满宽度的效果,目标是让图表区域完全占满设定宽度,同时图例分两栏在底部左右排列。

原始代码

fig4 = go.Figure()
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['A'], name='Combustíveis e lubrificantes'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['B'], name='Hipermercados, supermercados, alimentos, bebidas e fumo'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['C'], name='Tecidos, vestuário e calçados'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['D'], name='Móveis e eletrodomésticos'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['E'], name='Artigos farmacêuticos, médicos, ortopédicos, de perfumaria e cosméticos'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['F'], name='Livros, jornais, revistas e papelaria'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['G'], name='Equipamentos e materiais para escritório, informática e comunicação'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['H'], name='Outros artigos de uso pessoal e doméstico'))

fig4.update_layout(title={'text':'PMC: Pesquisa Mensal de Comércio - Nível SA', 'x':0.5, 'xanchor': 'center'},
                   template='plotly_white',width=975,height=525,
                   xaxis=dict(showticklabels=True, showgrid=True),
                   yaxis=dict(range=[-100,100], ticksuffix="%"),
                   legend=dict(y=-0.2, orientation='h'),
                   )

原始效果

图例横向排列在图表底部,因文本过长导致图表区域被压缩,无法占满设定的975px宽度,整体布局拥挤。

期望效果

图表区域完全占满设定宽度,8个图例分为两组,每组4个,分别在底部左右两侧横向排列,不挤占图表显示空间。

修改后尝试代码(未达预期)

fig4 = go.Figure()
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['A'], name='Combustíveis e lubrificantes'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['B'], name='Hipermercados, supermercados, alimentos, bebidas e fumo'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['C'], name='Tecidos, vestuário e calçados'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['D'], name='Móveis e eletrodomésticos'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['E'], name='Artigos farmacêuticos, médicos, ortopédicos, de perfumaria e cosméticos', legend='legend2'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['F'], name='Livros, jornais, revistas e papelaria', legend='legend2'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['G'], name='Equipamentos e materiais para escritório, informática e comunicação', legend='legend2'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['H'], name='Outros artigos de uso pessoal e doméstico', legend='legend2'))
fig4.update_layout(title={'text':'PMC: Pesquisa Mensal de Comércio - Nível SA', 'x':0.5, 'xanchor': 'center'},
                   template='plotly_white',width=975,height=525,
                   xaxis=dict(showticklabels=True, showgrid=True),
                   yaxis=dict(range=[-100,100], ticksuffix="%"),
                   legend=dict(yanchor='bottom', xanchor='left', y=-1, x=-0.5, orientation='h'),
                   legend2=dict(yanchor='bottom', xanchor='right', y=-1, x=1.5, orientation='h'),
                   margin=dict(pad=100),
                   paper_bgcolor="LightSteelBlue" # 用于在Stack Overflow帖子中更好地可视化
                   )

修改后效果

图表被压缩到页面中间,左右两侧出现大量留白,两组图例分别显示在左右留白区域,未实现图表占满宽度的目标。

解决方案代码

fig4 = go.Figure()
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['A'], name='Combustíveis e lubrificantes'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['B'], name='Hipermercados, supermercados, alimentos, bebidas e fumo'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['C'], name='Tecidos, vestuário e calçados'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['D'], name='Móveis e eletrodomésticos'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['E'], name='Artigos farmacêuticos, médicos, ortopédicos, de perfumaria e cosméticos', legend='legend2'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['F'], name='Livros, jornais, revistas e papelaria', legend='legend2'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['G'], name='Equipamentos e materiais para escritório, informática e comunicação', legend='legend2'))
fig4.add_trace(go.Scatter(x=df_mm3m_sa.index, y=df_mm3m_sa['H'], name='Outros artigos de uso pessoal e doméstico', legend='legend2'))

fig4.update_layout(
    title={'text':'PMC: Pesquisa Mensal de Comércio - Nível SA', 'x':0.5, 'xanchor': 'center'},
    template='plotly_white',
    width=975,
    height=525,
    xaxis=dict(showticklabels=True, showgrid=True),
    yaxis=dict(range=[-100,100], ticksuffix="%"),
    # 主图例靠左对齐,放在底部相对坐标0位置
    legend=dict(
        yanchor='bottom',
        xanchor='left',
        y=-0.3,  # 调整y值控制图例与图表的距离
        x=0,
        orientation='h',
        itemwidth=30  # 控制图例项宽度,避免文本换行
    ),
    # 第二组图例靠右对齐,放在底部相对坐标1位置
    legend2=dict(
        yanchor='bottom',
        xanchor='right',
        y=-0.3,
        x=1,
        orientation='h',
        itemwidth=30
    ),
    # 调整底部margin,给图例留出足够空间,同时让图表占满宽度
    margin=dict(bottom=120, left=20, right=20, top=40),
    paper_bgcolor="white"
)

关键调整说明

  • 图例坐标改为相对值:将x设为0(左对齐)和1(右对齐),使用相对坐标避免挤占图表区域,确保图表占满设定的宽度。
  • 调整底部边距:设置margin.bottom=120,为底部的两组图例预留足够显示空间,同时减少左右边距避免图表留白。
  • 控制图例项宽度:通过itemwidth参数调整每个图例项的宽度,防止长文本换行或过于拥挤。
  • 统一图例垂直位置:两组图例设置相同的y=-0.3,保证在同一水平线上排列。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 01:38:09