Dear fellow learners,
For my own learning, I experimented with customizing the hover information. It was pretty straightforward for scatter plots but I was unable to achieve what I wanted in my box plot. Currently, the hover display includes the trace name and the stat value, e.g. (Europe, q3: $33,860)
.
I want to have it display Q3: $33,860
without the parentheses and the trace name (“Europe”). In addition, I also failed to remove or hide the secondary box (the red “Europe”) even though I used <extra></extra>
in the hovertemplate as suggested in the documentation.
I checked the documentation and online forums and tried many tips but to no avail. Hopefully, someone here can enlighten me. My code is pasted below. Thank you.
from dash import Dash, html, dcc, Input, Output, callback
import dash_ag_grid as dag
import plotly.express as px
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminder2007.csv')
columnDefs = [
{ 'field': 'country' },
{ 'field': 'pop' },
{ 'field': 'continent' },
{ 'field': 'lifeExp' },
{ 'field': 'gdpPercap' }
]
cat_vars = ['country', 'continent']
options_dict = {
'pop':'Population',
'lifeExp':'Life Expectancy',
'continent':'Continent'
}
style={'width': '80%', 'margin': 'auto'}
grid = dag.AgGrid(
id='tabular-data',
rowData=df.to_dict('records'),
columnDefs=columnDefs,
style=style
)
# Initialize the app
app = Dash(__name__)
# App layout
app.layout = html.Div([
html.H1(
children='Population, Life Expectancy and Per Capita GDP by Country/Continent',
style=style
),
html.Hr(),
dcc.RadioItems(
options=options_dict,
value='lifeExp',
inline=True,
style=style,
id='radio-buton'
),
html.P(),
grid,
dcc.Graph(
figure={},
style=style,
id='my-scatter'
)
])
# Add controls to build the interaction
@callback(
Output(component_id='my-scatter', component_property='figure'),
Input(component_id='radio-buton', component_property='value')
)
def update_graph(yaxis_chosen):
hover_template = None
if yaxis_chosen in cat_vars:
fig = px.box(
df,
x=yaxis_chosen,
y='gdpPercap',
color='continent',
custom_data=['country', 'continent'],
labels={
'gdpPercap': 'Per Capita GDP',
yaxis_chosen: options_dict.get(yaxis_chosen, yaxis_chosen)
}
)
fig.update_layout(
yaxis = dict(
tickformat='$,.0f'
)
)
for trace in fig.data:
trace.update(hoverinfo='y')
trace_color = trace.marker.color
hover_template = f'<b style="color: {trace_color}">%{{customdata[0]}}, %{{customdata[1]}}</b><br>Per Capita GDP: $%{{y:,.0f}}<extra></extra>'
trace.update(hovertemplate=hover_template)
else:
fig = px.scatter(
df,
x='gdpPercap',
y=yaxis_chosen,
color='continent',
custom_data=['country', 'continent'],
labels={
'gdpPercap': 'Per Capita GDP',
yaxis_chosen: options_dict.get(yaxis_chosen, yaxis_chosen)
}
)
fig.update_layout(
xaxis = dict(
tickformat='$,.0f'
)
)
pop_chosen = yaxis_chosen == 'pop'
for trace in fig.data:
trace_color = trace.marker.color
if pop_chosen:
hover_template = f'<b style="color: {trace_color}">%{{customdata[0]}}, %{{customdata[1]}}</b><br>Per Capita GDP: $%{{x:,.0f}}<br>{options_dict[yaxis_chosen]}: %{{y:,.0f}}<extra></extra>'
else:
hover_template = f'<b style="color: {trace_color}">%{{customdata[0]}}, %{{customdata[1]}}</b><br>Per Capita GDP: $%{{x:,.0f}}<br>{options_dict[yaxis_chosen]}: %{{y:.2f}}<extra></extra>'
trace.update(hovertemplate=hover_template)
if pop_chosen:
fig.update_yaxes(type='log')
fig.update_layout(
legend_title='Continent',
hoverlabel=dict(
bgcolor='rgba(255, 255, 255, 0.75)'
)
)
return fig
@callback(
Output(component_id='tabular-data', component_property='rowData'),
Output(component_id='tabular-data', component_property='columnDefs'),
Input(component_id='my-scatter', component_property='selectedData')
)
def update_table(selected_data):
if selected_data is None:
return df.to_dict("records"), columnDefs
countries_selected = []
for points in selected_data['points']:
countries_selected.append(points['customdata'][0])
print(countries_selected)
dff = df[df.country.isin(countries_selected)]
return dff.to_dict("records"), columnDefs
# Run the app
if __name__ == '__main__':
app.run(debug=True)