Using if / else in a hover_data dictinoary

Hey All;

I’m using the following dictionary as hover_data in a px.scatterplot:

hover_data = {
    "Marker" : False,
    "Glucose (mmol/L)" : True,
    "DateTime" : True,
    "Description" : True
}

The Description column either contains string values or nan. When I generate the scatterplot and hover over points where Description has nan values, the hover_data for these values shows the following:

Description=%{customdata[1]}

Here is a screenshot:

What I’d like to do is use an if / else statement to do the following:

Description : (False if value == nan else True)

But I’ve had no success. These are the two methods i’ve tried:
Method 1

"Description" : (False if i == nan else True for i in %{customdata[1]})

But I get this error:

SyntaxError: invalid syntax

Method 2

"Description" : (False if i == nan else True for i in df["Description"])

But I get this error:

ValueError: Ambiguous input: values for 'Description' appear both in hover_data and data_frame

Does anyone know if it’s possible to use an if / else to customize what is displayed in a hover_data dictionary? If it’s possible, can someone please explain how?

Many thanks!

Hi @iacisme

I don’t know if it’s possible to do exactly what you’re looking for, however, a hacky workaround would be to create a new column in the dataframe that returns the description or “no description available” and use that column in the hover_data dictionary. In my opinion, this is better than trying to take out the column from the hover_data for null values which could be confusing. Here’s a minimal sample code for how to do it:

import pandas as pd
import plotly.express as px

df = pd.DataFrame({
    'category': ['A', 'B', 'C', 'D'],
    'value': [10, 20, 30, 40],
    'description': ['This is A', 'This is B', None, 'This is D']
})


df['custom_hover'] = df['description'].apply(lambda x: x if pd.notnull(x) else 'no description available')

fig = px.bar(df, x='category', y='value', hover_data={'custom_hover': True})

fig.show()

EDIT: Or you could just fill those Null values in the ‘description’ column itself :sweat_smile:

3 Likes

Thanks for the suggestion!

I was hoping for a fancier way, but this might be the only way to handle this.

Cheers!

Hi @iacisme ,

This is just other alternatives for completely hide description that have nan values.
To do that, you can customize the hover data use hovertemplate.

Just like @mo.elauzei 's response, you still need to create additional new column and do nan filtering to achieve this result.

I assume in this example using ‘nan’ string, because I use description column as color column in scatter, just to make easier to compare when displaying the result.

Here is the purple point is nan point

and other ones have description.

If you interested in the code behind, here is the code:

import plotly.express as px
import pandas as pd 

# dummy dataframe
df = pd.DataFrame({'x': list(range(1,11)),
					'y': list(range(10,110,10)),
					'description': ['Excellent','Very Good','Good','nan','nan','Excellent','Very Good','Good','nan','nan']
				})

# create new column for description label in hovertemplate
# put <br> tag into description label so if the description is nan it will not print new line.
df['description_label'] = df['description'].apply(lambda x: '<br>description:' if x != 'nan' else '')

# create new column for description value in hovertemplate
df['description_value'] = df['description'].apply(lambda x: x if x != 'nan' else '')


# add new columns as custom_data
fig = px.scatter(df, 
					x='x', 
					y='y',
					color='description',
					custom_data=['description_label','description_value']
				)


# update new hovertemplate 
fig.update_traces(
			hovertemplate =
                "x data: %{x:.2f}<br>" +
                "y data: %{y:.2f}" +
                "%{customdata[0]} %{customdata[1]}" +
                "<extra></extra>"
                )


fig.update_traces(marker_size=14)
fig.show()
2 Likes

Thanks for this suggestion!

I’m going to play around with it to see if it works and get back to you.

Cheers!

1 Like