Hovertemplate with customdata or hover_data of variable shape

@Chilango74
To get help you should give a more precise information on your data:

  • first, a minimal data frame with (synthetic) data, similar to your actual data;
  • what do you mean by unknown shape of additional data? the number of columns is unknown or the number of elements in each additional column or both?

If the number of additional columns is unknown a priori, meaning that you intend to run the same code with different dataframes, then with Python it seems to be impossible to define the hovertemplate string, such that to display formated customdata.
If we have the following dataframe, then, theoretically, the hovertemplate should be defined as follows:

import plotly.graph_objects as go
import pandas as pd
import numpy as np
n=20
rsk=  np.sort(4+2*np.random.rand(n))
w= np.random.rand(2*n)
df= pd.DataFrame({"Risk": rsk, "Return":np.log(rsk), "col2": w[:n], "col3": w[n:]})
customdata = np.stack([df[n] for n in df.columns[2:]], axis=-1)
############################
addstring = "<b>Risk: %{x:.2f}% <br>Return: %{y:.2}%</b><BR>"
hstring=""
for k in range(2, len(df.columns)):
     hstring = hstring  + f "%{customdata[{k-2}]:.2f}%<br>"    
hovertemplate = addstring + "<br>weights:<br>" + hstring+"<extra></extra>"

But if you run this code you’ll get errors, because the string, hovertemplate, contains { }, by default, and when using python f-strings, you also must insert {k-2} to get customdata[0], and customdata[1], and these two kinds of { } cannot be interpreted correctly. There is a conflict between plotly.js requirements for the string hovertemplate, and Python interpretation of f-strings.
Since the Julia language uses another way to format the equivalent of python f-strings, in this language I was able to get the right displaying of hoverformat.

using PlotlyJS, DataFrames
n=20
rsk=  sort(4 .+2*rand(n))
w= rand(2*n)
df= DataFrame(Risk= rsk, Return=log.(rsk), col2= w[1:n], col3= w[n+1:2*n])

#############################################
addstring = "<b>Risk: %{x:.2f}% <br>Return: %{y:.2}%</b><BR>"
hstring=""
for k in 3:length(names(df))
    hstring = hstring*"%{customdata[$(k-3)]:.2f}%<br>"
end    
hovertemplate =addstring*"<br>weights:<br>"*hstring*"<extra></extra>"
#############################################

pl=Plot(scatter(
            x=df[!, :Risk],
            y=df[!, :Return],
            customdata=Matrix(df[!, 3:end])', ###Important!!!! python  customdata must be transposed  in Julia                      
            hovertemplate=hovertemplate,
            mode="lines",
            name="Efficient Frontier"
        )
    )

Let us printing the string hovertemplate:

print(hovertemplate)
<b>Risk: %{x:.2f}% <br>Return: %{y:.2}%</b><BR><br>weights:<br>%{customdata[0]:.2f}%<br>%{customdata[1]:.2f}%<br><extra></extra>

3 Likes