Plotly displays incomplete formatted trace name in legend box

Viewed 1418

I'm trying to get a formatted text as the trace name in a plotly plot, but the text comes out incomplete, as if the legend box cuts it short. The code is something like this:

trace1 = go.Scatter(x = [ 0.7686741,  0.90457  ,  1.140613 ,  1.395725 ,  1.7772   ,
        2.339876 ,  3.112365 ,  4.161422 ,  4.194801 ,  5.212864 ,
        6.371596 ,  7.396811 ,  7.604239 ,  7.969025 ,  8.355268 ,
        8.443485 ,  8.703365 ,  9.63798  , 10.97553  , 14.62577  ,
       14.75691  , 19.68748  ],
                    y = [20, 20, 21, 22, 23, 24, 25, 26, 25, 27, 28, 28, 29, 29, 30, 30, 30,
       31, 32, 35, 35, 40],
                    name = 'Process data',
                    mode = 'markers',
                    line_width = 2)

trace2 = go.Scatter(x = df['x'],
                    y = results.predict(),
                    mode = 'lines+markers',
                    name = '$y= -0.000359x^4 +0.0173x^3 -0.285x^2 +2.73x +18.4$',
                    hoverinfo = 'x+y',
                    line_width = 2,)

data = [trace1, trace2]

layout = go.Layout(template= 'simple_white',
                   legend = dict(font_size = 20,
                                 x = 0.02),
                    width = 1060, height = 550)

fig = go.Figure(data=data, layout=layout)
fig.show()

This generates the following plot:

enter image description here

If I set a font size > 14, the polynomial is cut by the legend box as you can see. I do need the big font size. Is there a different way to get the formatted trace name in the legend with a big font size without being cut?

Edit: removed the OLS results object, replaced x and y data and defined directly the tracename provoking the issue.

1 Answers

Second attempt

I finally managed to replicate your issue, and I had to use a very long expression: r'$y= -0.0003585x^4 +0.01732x^3 -0.2849x^2 +2.729x +18.35 => y= -0.0003585x^4 +0.01732x^3 -0.2849x^2 +2.729x +18.35$' to get this:

Plot 1:

enter image description here

And although it's not a very elegant approach, I do have suggestion on how to solve, or rather work around, the issue. I'm not 100% sure what's going on here. But it seems that after a certain length of the trace names, plotly will adjust the width of the element box to the length of the names in a different manner. And it seems that the length of the formatted name that is displayed is not the same as the length of the string used when you run the code. But we can get back to that. To make room for the full length of the huge formula above, I just added a bunch of empty spaces to the first name:

Plot 2:

enter image description here

Code 2:

import plotly.io as pio
pio.renderers.default='browser'

import plotly.graph_objects as go
import numpy as np

x = np.arange(10)

polyname = r'$y= -0.0003585x^4 +0.01732x^3 -0.2849x^2 +2.729x +18.35 => y= -0.0003585x^4 +0.01732x^3 -0.2849x^2 +2.729x +18.35$'
normalname = 'trace1'
normalname = normalname + ' '*180

fig = go.Figure(data=go.Scatter(x=x**6, y=x**4,
                                mode='lines+markers',
                                hovertemplate = '<i>y</i>:%{y:20,.2f}'+ '<br><b>x</b>: %{x}<br>',
                                #name = 'trace1'+(str([' ']*len(polyname)))
                                name=normalname))

fig.add_trace(go.Scatter(x=x**6, y=x**4.1, mode='markers', name = tracename))

fig.update_layout(
    legend=dict(
        x=0,
        y=1,
        traceorder="normal",
        font=dict(
            family="sans-serif",
            size=22,
            color="black"
        ),
        bgcolor="rgba(0,0,255,0.2)",
        bordercolor="Black",
        borderwidth=2
    )
)

fig.show()

As you can see, I've used 180 in normalname = normalname + ' '*180 to make enough room in the legend for the formatted name. A more elegant approach would be normalname = normalname + ' '*len(polyname) which is 114, but then it's right back to:

enter image description here

And this is why I think there's a difference in the lengths of the formatted name, and the number of characters in the string used as source for the formatted name r'$y= -0.0003585x^4 +0.01732x^3 -0.2849x^2 +2.729x +18.35 => y= -0.0003585x^4 +0.01732x^3 -0.2849x^2 +2.729x +18.35$'

Anyway, I hope this is something you can use.

Initial answer:

I'm assuming that you mean that the complete polynomial expression is cut off by the legend box. Are you sure that it does though? You see, I'm unable to replicate your problem. Even when using a trace name like 'very long polynomial expression that doesnt fit in the box':

enter image description here

This only becomes a problem when the name is longer than the plot itself. Either caused by the length of the string or size of the font:

enter image description here

So this should not be a problem in your case. Therefore I suspect it's the title itself that has not been formatted properly. Could you try and print it out and check it? And if you could share a data sample to reconstruct your plot it would be easier to help you out.

In addition, there is not option for specifying the size of the legend box:

Valid properties for object of type plotly.graph_objs.layout.Legend:

        bgcolor
            Sets the legend background color. Defaults to
            `layout.paper_bgcolor`.
        bordercolor
            Sets the color of the border enclosing the legend.
        borderwidth
            Sets the width (in px) of the border enclosing the
            legend.
        font
            Sets the font used to text the legend items.
        itemclick
            Determines the behavior on legend item click. "toggle"
            toggles the visibility of the item clicked on the
            graph. "toggleothers" makes the clicked item the sole
            visible item on the graph. False disable legend item
            click interactions.
        itemdoubleclick
            Determines the behavior on legend item double-click.
            "toggle" toggles the visibility of the item clicked on
            the graph. "toggleothers" makes the clicked item the
            sole visible item on the graph. False disable legend
            item double-click interactions.
        itemsizing
            Determines if the legend items symbols scale with their
            corresponding "trace" attributes or remain "constant"
            independent of the symbol size on the graph.
        orientation
            Sets the orientation of the legend.
        title
            :class:`plotly.graph_objects.layout.legend.Title`
            instance or dict with compatible properties
        tracegroupgap
            Sets the amount of vertical space (in px) between
            legend groups.
        traceorder
            Determines the order at which the legend items are
            displayed. If "normal", the items are displayed top-to-
            bottom in the same order as the input data. If
            "reversed", the items are displayed in the opposite
            order as "normal". If "grouped", the items are
            displayed in groups (when a trace `legendgroup` is
            provided). if "grouped+reversed", the items are
            displayed in the opposite order as "grouped".
        uirevision
            Controls persistence of legend-driven changes in trace
            and pie label visibility. Defaults to
            `layout.uirevision`.
        valign
            Sets the vertical alignment of the symbols with respect
            to their associated text.
        x
            Sets the x position (in normalized coordinates) of the
            legend. Defaults to 1.02 for vertical legends and
            defaults to 0 for horizontal legends.
        xanchor
            Sets the legend's horizontal position anchor. This
            anchor binds the `x` position to the "left", "center"
            or "right" of the legend. Value "auto" anchors legends
            to the right for `x` values greater than or equal to
            2/3, anchors legends to the left for `x` values less
            than or equal to 1/3 and anchors legends with respect
            to their center otherwise.
        y
            Sets the y position (in normalized coordinates) of the
            legend. Defaults to 1 for vertical legends, defaults to
            "-0.1" for horizontal legends on graphs w/o range
            sliders and defaults to 1.1 for horizontal legends on
            graph with one or multiple range sliders.
        yanchor
            Sets the legend's vertical position anchor This anchor
            binds the `y` position to the "top", "middle" or
            "bottom" of the legend. Value "auto" anchors legends at
            their bottom for `y` values less than or equal to 1/3,
            anchors legends to at their top for `y` values greater
            than or equal to 2/3 and anchors legends with respect
            to their middle otherwise.

Please let me know if I'm missing som details here!

Related