Plotly: Including additional data in hovertemplate
Question:
hovertemplate=
‘Continent: %{df[‘continent’]}
‘+
‘Country: %{df[‘country’]}
‘+
‘gdpPercap: %{x:,.4f}
‘+
‘lifeExp: %{y}’+
”
I’m trying to use hovertemplate to customize hover information. However I can’t get it to display what I want. I am getting x & y to work well. I can’t figure out how to add other fields to the hovertemplate though. Any help would be appreciated.
import numpy as np
df = df[df['year'] == 1952]
customdata = np.stack((df['continent'], df['country']), axis=-1)
fig = go.Figure()
for i in df['continent'].unique():
df_by_continent = df[df['continent'] == i]
fig.add_trace(go.Scatter(x=df_by_continent['gdpPercap'],
y=df_by_continent['lifeExp'],
mode='markers',
opacity=.7,
marker = {'size':15},
name=i,
hovertemplate=
'Continent: %{customdata[0]}<br>'+
'Country: %{customdata[1]}<br>'+
'gdpPercap: %{x:,.4f} <br>'+
'lifeExp: %{y}'+
'<extra></extra>',
))
fig.update_layout(title="My Plot",
xaxis={'title':'GDP Per Cap',
'type':'log'},
yaxis={'title':'Life Expectancy'},
)
fig.show()
Updated with more code. The first answer didn’t work just returning the text value of comdata.
Answers:
For any other variables besides {x}
and {y}
in the hovertemplate
string, you’ll want to create a variable called customdata
which is a numpy array of the DataFrame columns (df['continent'], df['country']
in your case), and pass customdata=customdata
to fig.update_layout
. This is suggested by @empet in his Plotly forum answer here.
You can try something like:
import numpy as np
import pandas as pd
import plotly.express as px
df = px.data.gapminder()
customdata = np.stack((df['continent'], df['country']), axis=-1)
fig = px.scatter(df, x="gdpPercap", y="lifeExp")
hovertemplate = ('Continent: %{customdata[0]}<br>' +
'Country: %{customdata[1]}<br>' +
'gdpPercap: %{x:,.4f} <br>' +
'lifeExp: %{y}' +
'<extra></extra>')
fig.update_traces(customdata=customdata, hovertemplate=hovertemplate)
fig.show()
See below for an additional example of how to use customdata
with multiple traces based on the code included in your question. Note that you actually need to add the customdata
to the figure traces in order to use it in the hovertemplate
, this was also shown in Derek O‘s answer.
import numpy as np
import pandas as pd
import plotly.graph_objects as go
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv')
df = df[df['year'] == 1952]
fig = go.Figure()
for continent in df['continent'].unique():
df_by_continent = df[df['continent'] == continent]
fig.add_trace(
go.Scatter(
x=df_by_continent['gdpPercap'],
y=df_by_continent['lifeExp'],
customdata=np.stack((df_by_continent['country'], df_by_continent['pop']), axis=-1),
mode='markers',
opacity=0.7,
marker={'size': 15},
name=continent,
hovertemplate='<b>Country</b>: %{customdata[0]}<br>' +
'<b>Population</b>: %{customdata[1]:,.0f}<br>' +
'<b>GDP</b>: %{x:$,.4f}<br>' +
'<b>Life Expectancy</b>: %{y:,.2f} Years' +
'<extra></extra>',
)
)
fig.update_layout(
xaxis={'title': 'GDP Per Cap', 'type': 'log'},
yaxis={'title': 'Life Expectancy'},
)
fig.write_html('fig.html', auto_open=True)
A variation of the previous answers using just pandas/python:
customdata = list(df[['continent','country']].to_numpy())
Then compose your figure with a template referring to customdata as in the other answers. For variation here’s an example with Scatter3D and adding data from two columns of a dataframe:
import plotly.graph_objects as go
customdata_set = list(df[['transaction','type']].to_numpy())
fig = go.Figure(
data=[go.Scatter3d(x=df.time,
y=df.source,
z=df.dest,
hovertemplate='<i>Source:</i>: %{y:i}<br>' +
'<i>Destination:</i>: %{z:i}<br>' +
'<i>Amount:</i>: $%{text}<br>' +
'<i>Txn #:</i>: %{customdata[0]}<br>' +
'<i>Txn Type:</i>: %{customdata[1]}<br>' +
'<i>Date:</i>: %{x|%Y-%m-%d}',
text=(df.amount).to_numpy(),
customdata = customdata_set,
mode='markers',
marker=dict(
color=moat_sql.tx_amount,
size=4,
opacity=.8,
showscale=True,
colorscale='Viridis',
colorbar=dict(
title=dict(text='Log Txn Amount',
side='bottom',
font={'color': 'red'}
)
)
)
)]
)
Instead of using customdata + hovertemplate
, you can just pass formatted text to the text
parameter directly. I found this simpler, and more powerful – for example if you don’t want the exact same formatting for all elements.
So this actually works:
text = your_df.map(
lambda row: f'<i>Source:</i>: %{row.source:i}<br>' +
f'<i>Destination:</i>: %{row.z:i}<br>' +
f'<i>Amount:</i>: $%{row.amount}<br>' +
f'<i>Txn #:</i>: %{row.txn}<br>' +
f'<i>Txn Type:</i>: %{row.txn_type}<br>' +
f'<i>Date:</i>: %{row.date|%Y-%m-%d}',
axis='columns'
)
go.Scatter3d(
...,
text=text,
...
)
The text
element doesn’t support full HTML, but I’ve seen it support at least the <br>
and <b>
tags.
It does not seem to support <h1>, <nbsp>, <hr>
tags.
I believe the same is true for hovertemplate
.
here is an example in Javascript using Plotly.js in case anyone is looking for it.:
<!DOCTYPE html>
<html>
<head><script src="https://cdn.plot.ly/plotly-2.14.0.min.js"></script></head>
<body>
<div id="myDiv" style="width: 100%; height: 100%;"></div>
<script>
// Define custom data
const customData = [
{
x: [1, 2, 3],
y: [4, 5, 6],
z: ["Potato", "Banana", "Tomato"]
}
];
// Define custom hovertemplate
const customHovertemplate = "X: %{x}<br>Y: %{y}<br>Z: %{customdata}";
// Define trace using custom data and hovertemplate
const trace = {
x: customData[0].x,
y: customData[0].y,
customdata: customData[0].z,
mode: "markers",
marker: { color: "blue", size: 12 },
type: "scatter",
hovertemplate: customHovertemplate
};
Plotly.newPlot("myDiv", [trace]);
</script>
</body>
</html>
hovertemplate=
‘Continent: %{df[‘continent’]}
‘+
‘Country: %{df[‘country’]}
‘+
‘gdpPercap: %{x:,.4f}
‘+
‘lifeExp: %{y}’+
”
I’m trying to use hovertemplate to customize hover information. However I can’t get it to display what I want. I am getting x & y to work well. I can’t figure out how to add other fields to the hovertemplate though. Any help would be appreciated.
import numpy as np
df = df[df['year'] == 1952]
customdata = np.stack((df['continent'], df['country']), axis=-1)
fig = go.Figure()
for i in df['continent'].unique():
df_by_continent = df[df['continent'] == i]
fig.add_trace(go.Scatter(x=df_by_continent['gdpPercap'],
y=df_by_continent['lifeExp'],
mode='markers',
opacity=.7,
marker = {'size':15},
name=i,
hovertemplate=
'Continent: %{customdata[0]}<br>'+
'Country: %{customdata[1]}<br>'+
'gdpPercap: %{x:,.4f} <br>'+
'lifeExp: %{y}'+
'<extra></extra>',
))
fig.update_layout(title="My Plot",
xaxis={'title':'GDP Per Cap',
'type':'log'},
yaxis={'title':'Life Expectancy'},
)
fig.show()
Updated with more code. The first answer didn’t work just returning the text value of comdata.
For any other variables besides {x}
and {y}
in the hovertemplate
string, you’ll want to create a variable called customdata
which is a numpy array of the DataFrame columns (df['continent'], df['country']
in your case), and pass customdata=customdata
to fig.update_layout
. This is suggested by @empet in his Plotly forum answer here.
You can try something like:
import numpy as np
import pandas as pd
import plotly.express as px
df = px.data.gapminder()
customdata = np.stack((df['continent'], df['country']), axis=-1)
fig = px.scatter(df, x="gdpPercap", y="lifeExp")
hovertemplate = ('Continent: %{customdata[0]}<br>' +
'Country: %{customdata[1]}<br>' +
'gdpPercap: %{x:,.4f} <br>' +
'lifeExp: %{y}' +
'<extra></extra>')
fig.update_traces(customdata=customdata, hovertemplate=hovertemplate)
fig.show()
See below for an additional example of how to use customdata
with multiple traces based on the code included in your question. Note that you actually need to add the customdata
to the figure traces in order to use it in the hovertemplate
, this was also shown in Derek O‘s answer.
import numpy as np
import pandas as pd
import plotly.graph_objects as go
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv')
df = df[df['year'] == 1952]
fig = go.Figure()
for continent in df['continent'].unique():
df_by_continent = df[df['continent'] == continent]
fig.add_trace(
go.Scatter(
x=df_by_continent['gdpPercap'],
y=df_by_continent['lifeExp'],
customdata=np.stack((df_by_continent['country'], df_by_continent['pop']), axis=-1),
mode='markers',
opacity=0.7,
marker={'size': 15},
name=continent,
hovertemplate='<b>Country</b>: %{customdata[0]}<br>' +
'<b>Population</b>: %{customdata[1]:,.0f}<br>' +
'<b>GDP</b>: %{x:$,.4f}<br>' +
'<b>Life Expectancy</b>: %{y:,.2f} Years' +
'<extra></extra>',
)
)
fig.update_layout(
xaxis={'title': 'GDP Per Cap', 'type': 'log'},
yaxis={'title': 'Life Expectancy'},
)
fig.write_html('fig.html', auto_open=True)
A variation of the previous answers using just pandas/python:
customdata = list(df[['continent','country']].to_numpy())
Then compose your figure with a template referring to customdata as in the other answers. For variation here’s an example with Scatter3D and adding data from two columns of a dataframe:
import plotly.graph_objects as go
customdata_set = list(df[['transaction','type']].to_numpy())
fig = go.Figure(
data=[go.Scatter3d(x=df.time,
y=df.source,
z=df.dest,
hovertemplate='<i>Source:</i>: %{y:i}<br>' +
'<i>Destination:</i>: %{z:i}<br>' +
'<i>Amount:</i>: $%{text}<br>' +
'<i>Txn #:</i>: %{customdata[0]}<br>' +
'<i>Txn Type:</i>: %{customdata[1]}<br>' +
'<i>Date:</i>: %{x|%Y-%m-%d}',
text=(df.amount).to_numpy(),
customdata = customdata_set,
mode='markers',
marker=dict(
color=moat_sql.tx_amount,
size=4,
opacity=.8,
showscale=True,
colorscale='Viridis',
colorbar=dict(
title=dict(text='Log Txn Amount',
side='bottom',
font={'color': 'red'}
)
)
)
)]
)
Instead of using customdata + hovertemplate
, you can just pass formatted text to the text
parameter directly. I found this simpler, and more powerful – for example if you don’t want the exact same formatting for all elements.
So this actually works:
text = your_df.map(
lambda row: f'<i>Source:</i>: %{row.source:i}<br>' +
f'<i>Destination:</i>: %{row.z:i}<br>' +
f'<i>Amount:</i>: $%{row.amount}<br>' +
f'<i>Txn #:</i>: %{row.txn}<br>' +
f'<i>Txn Type:</i>: %{row.txn_type}<br>' +
f'<i>Date:</i>: %{row.date|%Y-%m-%d}',
axis='columns'
)
go.Scatter3d(
...,
text=text,
...
)
The text
element doesn’t support full HTML, but I’ve seen it support at least the <br>
and <b>
tags.
It does not seem to support <h1>, <nbsp>, <hr>
tags.
I believe the same is true for hovertemplate
.
here is an example in Javascript using Plotly.js in case anyone is looking for it.:
<!DOCTYPE html>
<html>
<head><script src="https://cdn.plot.ly/plotly-2.14.0.min.js"></script></head>
<body>
<div id="myDiv" style="width: 100%; height: 100%;"></div>
<script>
// Define custom data
const customData = [
{
x: [1, 2, 3],
y: [4, 5, 6],
z: ["Potato", "Banana", "Tomato"]
}
];
// Define custom hovertemplate
const customHovertemplate = "X: %{x}<br>Y: %{y}<br>Z: %{customdata}";
// Define trace using custom data and hovertemplate
const trace = {
x: customData[0].x,
y: customData[0].y,
customdata: customData[0].z,
mode: "markers",
marker: { color: "blue", size: 12 },
type: "scatter",
hovertemplate: customHovertemplate
};
Plotly.newPlot("myDiv", [trace]);
</script>
</body>
</html>