Hover Text and Formatting in Python
How to use hover text and formatting in Python with Plotly.
New to Plotly?
Plotly is a free and open-source graphing library for Python. We recommend you read our Getting Started guide for the latest installation or upgrade instructions, then move on to our Plotly Fundamentals tutorials or dive straight in to some Basic Charts tutorials.
Hover Labels¶
One of the most deceptively-powerful features of interactive visualization using Plotly is the ability for the user to reveal more information about a data point by moving their mouse cursor over the point and having a hover label appear.
There are three hover modes available in Plotly. The default setting is layout.hovermode='closest'
, wherein a single hover label appears for the point directly underneath the cursor.
Hovermode closest
(default mode)¶
import plotly.express as px
df = px.data.gapminder().query("continent=='Oceania'")
fig = px.line(df, x="year", y="lifeExp", color="country", title="layout.hovermode='closest' (the default)")
fig.update_traces(mode="markers+lines")
fig.show()
Hovermode x
or y
¶
If layout.hovermode='x'
(or 'y'
), a single hover label appears per trace, for points at the same x
(or y
) value as the cursor. If multiple points in a given trace exist at the same coordinate, only one will get a hover label. In the line plot below we have forced markers to appear, to make it clearer what can be hovered over, and we have disabled the built-in Plotly Express hovertemplate
by setting it to None
, resulting in a more compact hover label per point:
import plotly.express as px
df = px.data.gapminder().query("continent=='Oceania'")
fig = px.line(df, x="year", y="lifeExp", color="country", title="layout.hovermode='x'")
fig.update_traces(mode="markers+lines", hovertemplate=None)
fig.update_layout(hovermode="x")
fig.show()
Unified hovermode¶
If layout.hovermode='x unified'
(or 'y unified'
), a single hover label appear, describing one point per trace, for points at the same x
(or y
) value as the cursor. If multiple points in a given trace exist at the same coordinate, only one will get an entry in the hover label. In the line plot below we have forced markers to appear, to make it clearer what can be hovered over, and we have disabled the built-in Plotly Express hovertemplate
by setting it to None
, resulting in a more compact entry per point in the hover label:
import plotly.express as px
df = px.data.gapminder().query("continent=='Oceania'")
fig = px.line(df, x="year", y="lifeExp", color="country", title="layout.hovermode='x unified'")
fig.update_traces(mode="markers+lines", hovertemplate=None)
fig.update_layout(hovermode="x unified")
fig.show()
Control hovermode with Dash¶
Dash is the best way to build analytical apps in Python using Plotly figures. To run the app below, run pip install dash
, click "Download" to get the code and run python app.py
.
Get started with the official Dash docs and learn how to effortlessly style & deploy apps like this with Dash Enterprise.
Change the hovermode below and try hovering over the points:
Sign up for Dash Club → Free cheat sheets plus updates from Chris Parmer and Adam Schroeder delivered to your inbox every two months. Includes tips and tricks, community apps, and deep dives into the Dash architecture. Join now.
Selecting a hovermode in a figure created with plotly.graph_objects
¶
The hovermode is a property of the figure layout, so you can select a hovermode no matter how you created the figure, either with plotly.express
or with plotly.graph_objects
. Below is an example with a figure created with plotly.graph_objects
. If you're not familiar with the structure of plotly figures, you can read the tutorial on creating and updating plotly figures.
import plotly.graph_objects as go
import numpy as np
t = np.linspace(0, 2 * np.pi, 100)
fig = go.Figure()
fig.add_trace(go.Scatter(x=t, y=np.sin(t), name='sin(t)'))
fig.add_trace(go.Scatter(x=t, y=np.cos(t), name='cost(t)'))
fig.update_layout(hovermode='x unified')
fig.show()
Hover on Subplots¶
New in 5.21
Use hoversubplots
to define how hover effects expand to additional subplots. With hoversubplots=axis
, hover effects are included on stacked subplots using the same axis when hovermode
is set to x
, x unified
, y
, or y unified
.
import plotly.graph_objects as go
import pandas as pd
from plotly import data
df = data.stocks()
layout = dict(
hoversubplots="axis",
title="Stock Price Changes",
hovermode="x",
grid=dict(rows=3, columns=1),
)
data = [
go.Scatter(x=df["date"], y=df["AAPL"], xaxis="x", yaxis="y", name="Apple"),
go.Scatter(x=df["date"], y=df["GOOG"], xaxis="x", yaxis="y2", name="Google"),
go.Scatter(x=df["date"], y=df["AMZN"], xaxis="x", yaxis="y3", name="Amazon"),
]
fig = go.Figure(data=data, layout=layout)
fig.show()
Customizing Hover Label Appearance¶
Hover label text and colors default to trace colors in hover modes other than unified
, and can be globally set via the layout.hoverlabel
attributes. Hover label appearance can also be controlled per trace in <trace>.hoverlabel
.
import plotly.express as px
df = px.data.gapminder().query("continent=='Oceania'")
fig = px.line(df, x="year", y="lifeExp", color="country", title="Custom layout.hoverlabel formatting")
fig.update_traces(mode="markers+lines")
fig.update_layout(
hoverlabel=dict(
bgcolor="white",
font_size=16,
font_family="Rockwell"
)
)
fig.show()
Customizing Hover text with Plotly Express¶
Plotly Express functions automatically add all the data being plotted (x, y, color etc) to the hover label. Many Plotly Express functions also support configurable hover text. The hover_data
argument accepts a list of column names to be added to the hover tooltip, or a dictionary for advanced formatting (see the next section). The hover_name
property controls which column is displayed in bold as the tooltip title.
Here is an example that creates a scatter plot using Plotly Express with custom hover data and a custom hover name.
import plotly.express as px
df_2007 = px.data.gapminder().query("year==2007")
fig = px.scatter(df_2007, x="gdpPercap", y="lifeExp", log_x=True,
hover_name="country", hover_data=["continent", "pop"])
fig.show()
Disabling or customizing hover of columns in plotly express¶
hover_data
can also be a dictionary. Its keys are existing columns of the dataframe
argument, or new labels. For an existing column, the values can be
False
to remove the column from the hover data (for example, if one wishes to remove the column of thex
argument)True
to add a different column, with default formatting- a formatting string starting with
:
for numbers d3-format's syntax, and|
for dates in d3-time-format's syntax, for example:.3f
,|%a
.
It is also possible to pass new data as values of the hover_data
dict, either as list-like data, or inside a tuple, which first element is one of the possible values described above for existing columns, and the second element correspond to the list-like data, for example (True, [1, 2, 3])
or (':.1f', [1.54, 2.345])
.
These different cases are illustrated in the following example.
import plotly.express as px
import numpy as np
df = px.data.iris()
fig = px.scatter(df, x='petal_length', y='sepal_length', facet_col='species', color='species',
hover_data={'species':False, # remove species from hover data
'sepal_length':':.2f', # customize hover for column of y attribute
'petal_width':True, # add other column, default formatting
'sepal_width':':.2f', # add other column, customized formatting
# data not in dataframe, default formatting
'suppl_1': np.random.random(len(df)),
# data not in dataframe, customized formatting
'suppl_2': (':.3f', np.random.random(len(df)))
})
fig.update_layout(height=300)
fig.show()
Customizing hover text with a hovertemplate¶
To customize the tooltip on your graph you can use the hovertemplate attribute of graph_objects
traces, which is a template string used for rendering the information that appear on hoverbox.
This template string can include variables
in %{variable} format, numbers
in d3-format's syntax, and date
in d3-time-format's syntax. In the example below, the empty <extra></extra>
tag removes the part of the hover where the trace name is usually displayed in a contrasting color. The <extra>
tag can be used to display other parts of the hovertemplate, it is not reserved for the trace name.
Note that a hovertemplate customizes the tooltip text, while a texttemplate customizes the text that appears on your chart.
Set the horizontal alignment of the text within tooltip with hoverlabel.align.
import plotly.graph_objects as go
fig = go.Figure(go.Scatter(
x = [1,2,3,4,5],
y = [2.02825,1.63728,6.83839,4.8485,4.73463],
hovertemplate =
'<i>Price</i>: $%{y:.2f}'+
'<br><b>X</b>: %{x}<br>'+
'<b>%{text}</b>',
text = ['Custom text {}'.format(i + 1) for i in range(5)],
showlegend = False))
fig.add_trace(go.Scatter(
x = [1,2,3,4,5],
y = [3.02825,2.63728,4.83839,3.8485,1.73463],
hovertemplate = 'Price: %{y:$.2f}<extra></extra>',
showlegend = False))
fig.update_layout(
hoverlabel_align = 'right',
title = "Set hover text with hovertemplate")
fig.show()
import plotly.graph_objects as go
fig = go.Figure(go.Pie(
name = "",
values = [2, 5, 3, 2.5],
labels = ["R", "Python", "Java Script", "Matlab"],
text = ["textA", "TextB", "TextC", "TextD"],
hovertemplate = "%{label}: <br>Popularity: %{percent} </br> %{text}"
))
fig.show()
Modifying the hovertemplate of a plotly express figure¶
plotly.express
automatically sets the hovertemplate but you can modify it using the update_traces
method of the generated figure. It helps to print the hovertemplate generated by plotly.express
in order to be able to modify it. One can also revert to the default hover information of traces by setting the hovertemplate to None
.
import plotly.express as px
df_2007 = px.data.gapminder().query("year==2007")
fig = px.scatter(df_2007, x="gdpPercap", y="lifeExp", log_x=True, color='continent'
)
print("plotly express hovertemplate:", fig.data[0].hovertemplate)
fig.update_traces(hovertemplate='GDP: %{x} <br>Life Expectancy: %{y}') #
fig.update_traces(hovertemplate=None, selector={'name':'Europe'}) # revert to default hover
print("user_defined hovertemplate:", fig.data[0].hovertemplate)
fig.show()
Specifying the formatting and labeling of custom fields in a Plotly Express figure using a hovertemplate¶
This example adds custom fields to a Plotly Express figure using the custom_data
parameter and then adds a hover template that applies d3 formats to each element of the customdata[n]
array and uses HTML to customize the fonts and spacing.
# %%
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
import math
import numpy as np
data = px.data.gapminder()
df = data[data['year']==2007]
df = df.sort_values(['continent', 'country'])
df.rename(columns={"gdpPercap":'GDP per capita', "lifeExp":'Life Expectancy (years)'}, inplace=True)
fig=px.scatter(df,
x='GDP per capita',
y='Life Expectancy (years)',
color='continent',
size=np.sqrt(df['pop']),
# Specifying data to make available to the hovertemplate
# The px custom_data parameter has an underscore, while the analogous graph objects customdata parameter has no underscore.
# The px custom_data parameter is a list of column names in the data frame, while the graph objects customdata parameter expects a data frame or a numpy array.
custom_data=['country', 'continent', 'pop'],
)
# Plotly express does not have a hovertemplate parameter in the graph creation function, so we apply the template with update_traces
fig.update_traces(
hovertemplate =
"<b>%{customdata[0]}</b><br>" +
"<b>%{customdata[1]}</b><br><br>" +
"GDP per Capita: %{x:$,.0f}<br>" +
"Life Expectation: %{y:.0f}<br>" +
"Population: %{customdata[2]:,.0f}" +
"<extra></extra>",
mode='markers',
marker={'sizemode':'area',
'sizeref':10},
)
fig.update_layout(
xaxis={
'type':'log'},
)
fig.show()
Hover Templates with Mixtures of Period data¶
New in v5.0
When displaying periodic data with mixed-sized periods (i.e. quarterly and monthly) in conjunction with x
or x unified
hovermodes and using hovertemplate
, the xhoverformat
attribute can be used to control how each period's X value is displayed, and the special %{xother}
hover-template directive can be used to control how the X value is displayed for points that do not share the exact X coordinate with the point that is being hovered on. %{xother}
will return an empty string when the X value is the one being hovered on, otherwise it will return (%{x})
. The special %{_xother}
, %{xother_}
and %{_xother_}
variations will display with spaces before, after or around the parentheses, respectively.
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Bar(
x=["2020-01-01", "2020-04-01", "2020-07-01"],
y=[1000, 1500, 1700],
xperiod="M3",
xperiodalignment="middle",
xhoverformat="Q%q",
hovertemplate="%{y}%{_xother}"
))
fig.add_trace(go.Scatter(
x=["2020-01-01", "2020-02-01", "2020-03-01",
"2020-04-01", "2020-05-01", "2020-06-01",
"2020-07-01", "2020-08-01", "2020-09-01"],
y=[1100,1050,1200,1300,1400,1700,1500,1400,1600],
xperiod="M1",
xperiodalignment="middle",
hovertemplate="%{y}%{_xother}"
))
fig.update_layout(hovermode="x unified")
fig.show()
Advanced Hover Template¶
This produces the same graphic as in "Specifying the formatting and labeling of custom fields in a Plotly Express figure using a hovertemplate" above, but does so with the customdata
and text
parameters of graph_objects
. It shows how to specify columns from a dataframe to include in the customdata
array using the df[["col_i", "col_j"]]
subsetting notation. It then references those variables using e.g. %{customdata[0]}
in the hovertemplate. It includes comments about major differences between the parameters used by graph_objects
and plotly.express
.
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
import math
data = px.data.gapminder()
df_2007 = data[data['year']==2007]
df_2007 = df_2007.sort_values(['continent', 'country'])
bubble_size = []
for index, row in df_2007.iterrows():
bubble_size.append(math.sqrt(row['pop']))
df_2007['size'] = bubble_size
continent_names = ['Africa', 'Americas', 'Asia', 'Europe', 'Oceania']
continent_data = {continent:df_2007.query("continent == '%s'" %continent)
for continent in continent_names}
fig = go.Figure()
for continent_name, df in continent_data.items():
fig.add_trace(
go.Scatter(
x=df['gdpPercap'],
y=df['lifeExp'],
marker_size=df['size'],
text=df['continent'],
name=continent_name,
# The next three parameters specify the hover text
# Text supports just one customized field per trace
# and is implemented here with text=df['continent'],
# Custom data supports multiple fields through numeric indices in the hovertemplate
# In we weren't using the text parameter in our example,
# we could instead add continent as a third customdata field.
customdata=df[['country','pop']],
hovertemplate=
"<b>%{customdata[0]}</b><br>" +
"<b>%{text}</b><br><br>" +
"GDP per Capita: %{x:$,.0f}<br>" +
"Life Expectancy: %{y:.0f}<br>" +
"Population: %{customdata[1]:,.0f}" +
"<extra></extra>",
))
fig.update_traces(
mode='markers',
marker={'sizemode':'area',
'sizeref':10})
fig.update_layout(
xaxis={
'title':'GDP per capita',
'type':'log'},
yaxis={'title':'Life Expectancy (years)'})
fig.show()
Adding other data to the hover with customdata and a hovertemplate¶
go
traces have a customdata
argument in which you can add an array, which outer dimensions should have the same dimensions as the plotted data. You can then use customdata
inside a hovertemplate
to display the value of customdata.
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
np.random.seed(0)
z1, z2, z3 = np.random.random((3, 7, 7))
customdata = np.dstack((z2, z3))
fig = make_subplots(1, 2, subplot_titles=['z1', 'z2'])
fig.add_trace(go.Heatmap(
z=z1,
customdata=np.dstack((z2, z3)),
hovertemplate='<b>z1:%{z:.3f}</b><br>z2:%{customdata[0]:.3f} <br>z3: %{customdata[1]:.3f} ',
coloraxis="coloraxis1", name=''),
1, 1)
fig.add_trace(go.Heatmap(
z=z2,
customdata=np.dstack((z1, z3)),
hovertemplate='z1:%{customdata[0]:.3f} <br><b>z2:%{z:.3f}</b><br>z3: %{customdata[1]:.3f} ',
coloraxis="coloraxis1", name=''),
1, 2)
fig.update_layout(title_text='Hover to see the value of z1, z2 and z3 together')
fig.show()
Setting the Hover Template in Tile Maps¶
import plotly.graph_objects as go
fig = go.Figure(go.Scattermap(
name = "",
mode = "markers+text+lines",
lon = [-75, -80, -50],
lat = [45, 20, -20],
marker = {'size': 20, 'symbol': ["bus", "harbor", "airport"]},
hovertemplate =
"<b>%{marker.symbol} </b><br><br>" +
"longitude: %{lon}<br>" +
"latitude: %{lat}<br>" ))
fig.update_layout(
map = {
'style': "outdoors", 'zoom': 1},
showlegend = False)
fig.show()
Controlling Hover Text with graph_objects
and hoverinfo
¶
Prior to the addition of hovertemplate
, hover text was controlled via the now-deprecated hoverinfo
attribute.
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Scatter(
x=[1, 2, 3, 4, 5],
y=[2, 1, 6, 4, 4],
hovertext=["Text A", "Text B", "Text C", "Text D", "Text E"],
hoverinfo="text",
marker=dict(
color="green"
),
showlegend=False
))
fig.show()
Spike lines¶
Plotly supports "spike lines" which link a point to the axis on hover, and can be configured per axis.
import plotly.express as px
df = px.data.gapminder().query("continent=='Oceania'")
fig = px.line(df, x="year", y="lifeExp", color="country", title="Spike lines active")
fig.update_traces(mode="markers+lines")
fig.update_xaxes(showspikes=True)
fig.update_yaxes(showspikes=True)
fig.show()
Spike lines can be styled per axis as well, and the cursor distance setting can be controlled via layout.spikedistance
.
import plotly.express as px
df = px.data.gapminder().query("continent=='Oceania'")
fig = px.line(df, x="year", y="lifeExp", color="country", title="Styled Spike Lines")
fig.update_traces(mode="markers+lines")
fig.update_xaxes(showspikes=True, spikecolor="green", spikesnap="cursor", spikemode="across")
fig.update_yaxes(showspikes=True, spikecolor="orange", spikethickness=2)
fig.update_layout(spikedistance=1000, hoverdistance=100)
fig.show()
Reference¶
See https://plotly.com/python/reference/ for more information and chart attribute options!
What About Dash?¶
Dash is an open-source framework for building analytical applications, with no Javascript required, and it is tightly integrated with the Plotly graphing library.
Learn about how to install Dash at https://dash.plot.ly/installation.
Everywhere in this page that you see fig.show()
, you can display the same figure in a Dash application by passing it to the figure
argument of the Graph
component from the built-in dash_core_components
package like this:
import plotly.graph_objects as go # or plotly.express as px
fig = go.Figure() # or any Plotly Express function e.g. px.bar(...)
# fig.add_trace( ... )
# fig.update_layout( ... )
from dash import Dash, dcc, html
app = Dash()
app.layout = html.Div([
dcc.Graph(figure=fig)
])
app.run_server(debug=True, use_reloader=False) # Turn off reloader if inside Jupyter