Legendgroup horizontal spacing - missing feature?

Hello!

Below is provided a code snippet generating a chart with 3 subplots from a px dataset. I’m struggling to position the legend names accurately. When digging into the rendered page, I can’t figure out what CSS/SVG property I have to trick to achieve the desired output. At first, it looks like we miss a features like “tracegroupgap”, to set the horizontal spacing between each legend groups. The goal is to position every legendgroup at the bottom right corner of each subplot.

The code:

import plotly.graph_objects as go
import plotly.express as px
df = px.data.tips()

fig =go.Figure()
# fig6 = make_subplots(rows=1, cols=6, shared_yaxes="rows")
fig.add_trace(go.Bar(
    x=df.groupby(["day"])["total_bill"].min(), y=df.groupby(["day"])["total_bill"].sum().index,
    marker=dict(color='rgba(120,255,186, 0.6)'), orientation="h", name="traceA_One", xaxis="x", yaxis="y",
    legendgroup=1, legendrank=2, offset=-0.5, offsetgroup="1",
))
fig.add_trace(go.Bar(
    x=df.groupby(["day"])["total_bill"].max(), y=df.groupby(["day"])["total_bill"].sum().index,
    marker=dict(color='rgba(180,255,186, 0.6)'), orientation="h", name="traceA_Two", xaxis="x", yaxis="y",
    legendgroup=1, legendrank=2, offset=-0.3, offsetgroup="2",
))
fig.add_trace(go.Bar(
    x=df.groupby(["day"])["total_bill"].mean(), y=df.groupby(["day"])["total_bill"].sum().index,
    marker=dict(color='rgba(180,255,186, 0.6)'), orientation="h", name="traceB_One", xaxis="x2", yaxis="y",
    legendgroup=2,
))
fig.add_trace(go.Bar(
    x=df.groupby(["day"])["total_bill"].median(), y=df.groupby(["day"])["total_bill"].sum().index,
    marker=dict(color='rgba(150,148,186, 0.6)'), orientation="h", name="traceC_One", xaxis="x3", yaxis="y",
    legendgroup=3,
))
fig.update_layout(
    xaxis=dict(domain=[0.0, 0.32]), xaxis2=dict(domain=[0.34, 0.66]), xaxis3=dict(domain=[0.68, 1]),
    yaxis=dict(anchor="x", domain=[0.0, 0.98]), margin=dict(l=10, r=10, b=0, t=40), barmode="overlay", bargap=0.3,
    legend=dict(
        yanchor="bottom", y=0, xanchor="left", x=0, orientation="h", itemsizing="constant", borderwidth=0, 
        bgcolor="rgba(100,100,100,0.25)", itemwidth=30, entrywidthmode="fraction", entrywidth=0.33, tracegroupgap=0
    ),
)
fig.show()

Each subplot has a domain of length (1-(nbrOfSubplot-1)*gapLength)/nbrOfSubplots. So, in my case:

  • 1st domain goes from 0 to 0.32, then there is a gap of 0.02,
  • 2nd domain goes from 0.34 to 0.66, then there is a gap of 0.02
  • 3rd domain goes from 0.68 to 1

My “legend area” contains legendgroups that are displayed horizontally. Within each legendgroup, legend names are displayed vertically.

The central part of the issue lies in this:

    legend=dict(
        yanchor="bottom", y=0, xanchor="left", x=0, orientation="h", 
        itemsizing="constant", itemwidth=50,
        entrywidthmode="fraction", entrywidth=0.32,
        bgcolor="rgba(100,100,100,0.25)",
        tracegroupgap=0, borderwidth=0
    ),

With a tracegroupgap = 0 and an entrywidth of 0.32, the first legendgroup does have a width of 0.32. It ends at the end of the first xaxis domain. However, the 3 legend group are not displayed side by side: there is a gap between each of them:


On the above screenshot, I’ve highlighted the legend name zone by adding a SVG rect via the browser’s inspection tool, prior to take the screenshot.

If I set the entrywidth to 0.32+0.02, then I get this:


Again, legends names area are highlighted in dark grey/light red via the browser inspection tool

The last legendgroup is pushed on a new “row”, probably because 0.34*3>1
Since the tracegroupgap is set on 0, there is no space between the first group of legend names, and the third group. Should the tracegroupgap be 50, then there would be 50px white space.

Therefore, to achieve the desired output, I would need to

  1. set the entrywidth to 0.32
  2. define a kind of “horizontal” trace group gap of 0.02 (fraction, not pixel)
    This way the first legendgroup would span from 0 to 0.32, then there would be a gap of 0.02, etc.

Is there a workaround to do that by removing the default value of the horizontal gap, maybe?

Hi @David22 are you using dash as the tag of the topic indicates? If so, you could split each subplot into a separate figure.

The legend and it’s options is somewhat limited, IMHO

Hi @AIMPED, yes I do use Dash; for the sake of simplicity I provided a code generating a plotly figure only., without dash.
I could indeed split each subplots into a separate figure but then the legend names and groups would be independant the ones from the others. Will try next week and see if it’s really a problem.
Thanks