Mibi
Mibi

Reputation: 298

Plotly add hline to existing legend entry from scatter plot

I have a scatter plot with two or more different data sets. For each data set I also added a hline of their means. I would like to link the hline to the legend of the corresponding dataset so that if I deselect a dataset in the legend, the hline disappears as well.

Is this possible in plotly?

import pandas as pd
import plotly.graph_objects as go

df = pd.DataFrame({'x': [0, 1, 2],
                   'y1': [5, 4, 7],
                   'y2': [2, 3, 1]})
fig = go.Figure()

fig.add_trace(go.Scatter(
    x=df['x'],
    y=df['y1'],
    mode='markers',
    name='y1'
))

fig.add_trace(go.Scatter(
    x=df['x'],
    y=df['y2'],
    mode='markers',
    name='y2'
))

fig.add_hline(y=df['y1'].mean())
fig.add_hline(y=df['y2'].mean())

fig.show()

Upvotes: 1

Views: 2339

Answers (2)

chaosink
chaosink

Reputation: 1483

A workaround is that: For each horizontal/vertical line, draw a Scatter line with the same color and visible="legendonly".

It's worth noting that lines with visible="legendonly" show in the legend with half alpha. So for correspondence, you'd better use alpha 0.5 to draw the horizontal/vertical lines and use alpha 1.0 to draw the invisible lines.

enter image description here

import pandas as pd
import plotly.graph_objects as go
import plotly.express as px

COLORS = px.colors.qualitative.Plotly


def hex_to_rgba(h, alpha):
    """
    converts color value in hex format to rgba format with alpha transparency
    """
    return tuple([int(h.lstrip("#")[i : i + 2], 16) for i in (0, 2, 4)] + [alpha])


df = pd.DataFrame({"x": [0, 1, 2], "y1": [5, 4, 7], "y2": [2, 3, 1]})
fig = go.Figure()

fig.add_trace(go.Scatter(x=df["x"], y=df["y1"], mode="markers", name="y1"))
fig.add_trace(go.Scatter(x=df["x"], y=df["y2"], mode="markers", name="y2"))

fig.add_hline(
    y=df["y1"].mean(),
    line={
        "color": "rgba" + str(hex_to_rgba(h=COLORS[0], alpha=0.5)),
    },
)
fig.add_trace(
    go.Scatter(
        x=df["x"],
        y=df["y2"],
        mode="lines",
        visible="legendonly",
        name="y1 mean",
        line={
            "color": COLORS[0],
        },
    )
)

fig.add_hline(
    y=df["y2"].mean(),
    line={
        "color": "rgba" + str(hex_to_rgba(h=COLORS[1], alpha=0.5)),
    },
)
fig.add_trace(
    go.Scatter(
        x=df["x"],
        y=df["y2"],
        mode="lines",
        visible="legendonly",
        name="y2 mean",
        line={
            "color": COLORS[1],
        },
    )
)

fig.show()

Upvotes: 0

r-beginners
r-beginners

Reputation: 35205

First, it must be graphically supported to be reflected in the legend. So we draw a line using the line mode of the scatter plot. Then, set up a legend group to group the scatter and line graphs. Once this is done, you can show or hide the legend by clicking on it.

The second image is an example of the y2 legend clicked to hide it.

import pandas as pd
import plotly.graph_objects as go

df = pd.DataFrame({'x': [0, 1, 2],
                   'y1': [5, 4, 7],
                   'y2': [2, 3, 1]})
fig = go.Figure()

fig.add_trace(go.Scatter(
    x=df['x'],
    y=df['y1'],
    mode='markers',
    name='y1',
    legendgroup='1'
))

fig.add_trace(go.Scatter(
    x=df['x'],
    y=df['y2'],
    mode='markers',
    name='y2',
    legendgroup='2'

))

fig.add_trace(
    go.Scatter(
        mode='lines',
        x=df['x'],
        y=[df['y1'].mean()]*len(df),
        line_color='blue',
        legendgroup='1'
    )
)
             
fig.add_trace(
    go.Scatter(
        mode='lines',
        x=df['x'],
        y=[df['y2'].mean()]*len(df),
        line_color='red',
        legendgroup='2'
    )
)

fig.show()

enter image description here

enter image description here

Upvotes: 1

Related Questions