pythonplotly

Plotly's legend2 not allowing graphs full width


I'm making a plotly chart with many height length legends. Because of the number of legends and their length, I'm having issues with the legend automatic position property of plotly and I'm not having success on doing it by myself.

Code:

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'),
                   )

Output: enter image description here

What I want: enter image description here

I did some research and found out about "legend2" which could separate the legends in 2 blocks, so then I could put them on the bottom separately. It didn't work. The code below is an edit of the code above where I tried to separate the legends.

Code edited:

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" # Used for better visualization on the stackoverflow post
                   )
                   )

Output edit: enter image description here


Solution

  • I use some of the sample data in the reference with some modifications to suit your assignment. I also tried a method that does not use Legend2 for the horizontal legends in the reference. It is possible to specify the width of the item name in the legend in pixels. But you need to have enough height and width for the graph. I found the height and width by trial and error.

    import plotly.express as px
    import plotly.graph_objects as go
    
    df = px.data.stocks()
    df.columns = ['date','A','B','C','D','E','F']
    names = ['Combustíveis e lubrificantes', 'Hipermercados, supermercados, alimentos, bebidas e fumo',
                  'Tecidos, vestuário e calçados','Móveis e eletrodomésticos', 'Artigos farmacêuticos, médicos, ortopédicos, de perfumaria e cosméticos',
                  'Livros, jornais, revistas e papelaria']
    df['G'] = df['A']*1.1
    df['H'] = df['B']*1.2
    df.set_index('date', inplace=True)
    
    fig = go.Figure()
    for c,n in zip(df.columns, names):
        fig.add_trace(go.Scatter(
            x=df.index,
            y=df[c],
            name=n,
        ))
    
    fig.update_layout(
        title={'text':'PMC: Pesquisa Mensal de Comércio - Nível SA', 'x':0.5, 'xanchor': 'center'},
        template='plotly_white',
        width=1200,
        height=800,
        xaxis=dict(showticklabels=True, showgrid=True),
        yaxis=dict(range=[0.5,2], ticksuffix="%"),
        paper_bgcolor="LightSteelBlue"
    )
    
    fig.update_layout(legend=dict(
        orientation='h',
        yanchor='bottom',
        xanchor='left',
        entrywidthmode='pixels',
        entrywidth=440,
        y=-6,
        x=0
    ))
    fig.show()
    

    enter image description here