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
相关产品推荐
相关产品推荐

