Legend Title in Plotly

Plotly legend title

Update:

For not defining the legend but having the annotation positioned property please use the below code.

import plotly.offline as py_offline
import plotly.graph_objs as go
py_offline.init_notebook_mode()

trace0 = go.Scatter(
x=[1, 2, 3, 4, 5],
y=[1, 2, 3, 4, 5],
)

trace1 = go.Scatter(
x=[1, 2, 3, 4, 5],
y=[5, 4, 3, 2, 1],
)

data = [trace0, trace1]
layout = go.Layout(
annotations=[
dict(
x=1.12,
y=1.05,
align="right",
valign="top",
text='Legend Title',
showarrow=False,
xref="paper",
yref="paper",
xanchor="center",
yanchor="top"
)
]
)
fig = go.Figure(data=data, layout = layout)

py_offline.iplot(fig)

Notes:

  1. You need to define x and y position for annotations using this method, for varying legends.

  2. You can use html inside the text attribute(E.g: text='Legend Title<br>kinda lengthy',)

Previous Attempt:

Another approach would to create the legend and use annotations to add the title to the legend. Provided you do not use the graph in editable mode. So in the below example, the legend is set to x=0 and y=1, since I want my legend title to be above my actual legend, I set the annotation location as x = 0, y= 1.5. x-ref and y-ref needs to be set to paper. This will give a nice annotation like
plotly legend title

Code:

import plotly.plotly as py
import plotly.graph_objs as go

trace0 = go.Scatter(
x=[1, 2, 3, 4, 5],
y=[1, 2, 3, 4, 5],
)

trace1 = go.Scatter(
x=[1, 2, 3, 4, 5],
y=[5, 4, 3, 2, 1],
)

data = [trace0, trace1]
layout = go.Layout(
legend=dict(
x=0,
y=1,
traceorder='normal',
font=dict(
family='sans-serif',
size=12,
color='#000'
),
bgcolor='#E2E2E2',
bordercolor='#FFFFFF',
borderwidth=2
),
annotations=[
dict(
x=0,
y=1.05,
xref='paper',
yref='paper',
text='Legend Title',
showarrow=False
)
]
)
fig = go.Figure(data=data, layout = layout)

py.iplot(fig)

Plotly scatterplot legends not displaying legend title, but with = sign for each color

It's hard to tell exactly what's happening here without a reproducible example. To my knowledge, a proper application of px.scatter shouldn't render the result you're displaying. At least not for newer versions of Plotly. But in either case, and for full flexibility, you can run the two following lines to insert a legend title, and display only the text for each legend element that appears after the '=':

fig.for_each_trace(lambda t: t.update(name=t.name.split("=")[-1]))
fig.update_layout(legend_title_text = '<b>your title</b>')

Plot 1 - Before corrections:

Sample Image

Plot 2 - After corrections:

Sample Image

Complete code:

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

# data
df = px.data.iris()

# adjust data to reproduce the problem
df['species'] = ['species=' + s for s in df['species']]

# build figure
fig = px.scatter(df, x='petal_length', y = 'petal_width', color = 'species')

# change legend entries
fig.for_each_trace(lambda t: t.update(name=t.name.split("=")[-1]))

# edit title and show figure
fig.update_layout(legend_title_text = '<b>Custom title</b>')
fig.show()

Plotly: How to change variable/label names for the legend in a plotly express line chart?

The answer:

Without changing the data source, a complete replacement of names both in the legend, legendgroup and hovertemplate will require:

newnames = {'col1':'hello', 'col2': 'hi'}
fig.for_each_trace(lambda t: t.update(name = newnames[t.name],
legendgroup = newnames[t.name],
hovertemplate = t.hovertemplate.replace(t.name, newnames[t.name])
)
)

Plot:

Sample Image

The details:

Using

fig.for_each_trace(lambda t: t.update(name = newnames[t.name]))

...you can change the names in the legend without ghanging the source by using a dict

newnames = {'col1':'hello', 'col2': 'hi'}

...and map new names to the existing col1 and col2 in the following part of the figure structure (for your first trace, col1):

{'hovertemplate': 'variable=col1<br>index=%{x}<br>value=%{y}<extra></extra>',
'legendgroup': 'col1',
'line': {'color': '#636efa', 'dash': 'solid'},
'mode': 'lines',
'name': 'hello', # <============================= here!
'orientation': 'v',
'showlegend': True,
'type': 'scatter',
'x': array([0, 1, 2], dtype=int64),
'xaxis': 'x',
'y': array([1, 2, 3], dtype=int64),
'yaxis': 'y'},

But as you can see, this doesn't do anything with 'legendgroup': 'col1', nor 'hovertemplate': 'variable=col1<br>index=%{x}<br>value=%{y}<extra></extra>' And depending on the complexity of your figure, this can pose a problem. So I would add legendgroup = newnames[t.name] and hovertemplate = t.hovertemplate.replace(t.name, newnames[t.name])into the mix.

Complete code:

import pandas as pd
import plotly.express as px
from itertools import cycle

d = {'col1': [1, 2, 3], 'col2': [3, 4, 5]}
df = pd.DataFrame(data=d)
fig = px.line(df, x=df.index, y=['col1', 'col2'])

newnames = {'col1':'hello', 'col2': 'hi'}
fig.for_each_trace(lambda t: t.update(name = newnames[t.name],
legendgroup = newnames[t.name],
hovertemplate = t.hovertemplate.replace(t.name, newnames[t.name])
)
)

Add title to the plotly legend

The only way I know is to use an annotation and add it to the plot. Like this:

legendtitle <- list(yref='paper',xref="paper",y=1.05,x=1.1, text="Cylinders",showarrow=F)

mtcars %>% plot_ly(x = ~disp, y = ~mpg, color = ~factor(cyl), size = ~wt) %>%
add_markers( hoverinfo = "text",
text = ~paste("Displacement=",disp, "\nMiles Per Gallon = ", mpg)) %>%
layout(title ="Custom Hover Text", annotations=legendtitle )

Yielding:

Sample Image

It is a bit tricky to place the legend title though, not sure if this placement would always work.

Another way would be to use ggplot and ggplotly of course, and let ggplot figure it out.

Plotly: How to rename legend elements of a plotly express stacked bar plot?

map the data to the values you want

import plotly.express as px
long_df = px.data.medals_long()
fig = px.bar(long_df, x="nation", y="count",
color=long_df["medal"].map({"gold":"first","silver":"second","bronze":"third"}),
title="Long-Form Input")
fig.show()

How to make legend items bold in plotly

You can use a lambda function and some basic html formatting with:

fig.for_each_trace(lambda t: t.update(name = '<b>' + t.name +'</b>'))

And get:

Sample Image

If you'd like to highlight one or some of the legend entries you can sprinkle the previous statement with:

bold = 'versicolor'
fig.for_each_trace(lambda t: t.update(name = '<b>' + t.name +'</b>') if t.name in bold else())

And get:

Sample Image

Complete code:

import plotly.express as px

df = px.data.iris()
fig = px.scatter(df, x="sepal_length", y="sepal_width", color="species",
title="Automatic Labels Based on Data Frame Column Names")

# Plot 1
# fig.for_each_trace(lambda t: t.update(name = '<b>' + t.name +'</b>'))

# Plot 2
bold = 'versicolor'
fig.for_each_trace(lambda t: t.update(name = '<b>' + t.name +'</b>') if t.name in bold else())

fig.show()


Related Topics



Leave a reply



Submit