Search code examples
pythondataframeplotlyplotly-python

python plotly: how to display additional label on hover


I have two area subplots and when I hover over the plot, it displays the value of Val_2 and Val_Yellow. The dataframe contains a column called "Diff" that is the difference between Val_2 and Val_Yellow. How can I display Diff and its value in the bottom of the same white hover-box where Val_2 and Val_Yellow are displayed?

enter image description here

Here is the reproducible code:

import numpy as np
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots 

rng = pd.date_range('2022-04-09', periods=20, freq='D')
np.random.seed(42)
first_df = pd.DataFrame({ 'Date': rng, 'Val' : np.random.randn(len(rng))}) 
first_df['Type'] = 'A'

second_df = pd.DataFrame({ 'Date': rng, 'Val' : np.random.randn(len(rng))}) 
second_df['Type'] = 'B'

final_df =  pd.concat([first_df,second_df]).sort_values(by = 'Date')
final_df['Is_Weekend'] = np.where((final_df['Date'].dt.weekday == 5), 1, 0 )

final_df['Val_2'] = final_df['Val'] * 3
final_df['Diff'] = final_df['Val'] - final_df['Val_2']

A_df = final_df[final_df['Type']=='A']
B_df = final_df[final_df['Type']=='B']

fig = make_subplots(rows=2, cols=1,
                    vertical_spacing = 0.05,
                    shared_xaxes=True)
fig.add_trace(go.Scatter(
    x = A_df['Date'], 
    y = A_df['Val'],
    fill=None,
    mode='lines+markers',
    line_color='orange', showlegend=True, name = "Val_Yellow"),
            row = 1, col = 1)
fig.add_trace(go.Scatter(
    x =  A_df['Date'], 
    y = A_df['Val_2'],
    fill='tonexty', # fill area
    mode='lines+markers', line_color='red', showlegend=False, name ="Val_2"),
            row = 1, col = 1)
fig.update_xaxes(showgrid=False, row=1, col=1)


fig.add_trace(go.Scatter(
    x = B_df['Date'], 
    y = B_df['Val'],
    fill=None,
    mode='lines+markers',
    line_color='blue', showlegend=True, name = "Val_Blue"),
            row = 2, col = 1)

fig.add_trace(go.Scatter(
    x =  B_df['Date'], 
    y = B_df['Val_2'],
    fill='tonexty', # fill area
    mode='lines+markers', line_color='red', showlegend=True, name ="Val_2"),
            row = 2, col = 1)

fig.update_yaxes(tickprefix = "$")

fig.update_layout(hovermode='x unified', xaxis_range=[A_df['Date'].iloc[0], A_df['Date'].iloc[len(A_df)-1]])

Solution

  • You can use customdata to pass additional data for the hovertemplate to access. You will need to pass the "Diff" column from your dataframes into go.Scatter and then modify the hovertemplate to access the customdata.

    For example, I added customdata and hovertemplate arguments to your first go.Scatter trace:

    fig.add_trace(go.Scatter(
        x = A_df['Date'], 
        y = A_df['Val'],
        customdata = A_df['Diff'],
        hovertemplate = '%{y:$}<br>Diff:%{customdata:$}',
        fill=None,
        mode='lines+markers',
        line_color='orange', showlegend=True, name = "Val_Yellow"),
                row = 1, col = 1)
    

    I did the same for your third trace as well.

    import numpy as np
    import pandas as pd
    import plotly.graph_objects as go
    from plotly.subplots import make_subplots 
    
    rng = pd.date_range('2022-04-09', periods=20, freq='D')
    np.random.seed(42)
    first_df = pd.DataFrame({ 'Date': rng, 'Val' : np.random.randn(len(rng))}) 
    first_df['Type'] = 'A'
    
    second_df = pd.DataFrame({ 'Date': rng, 'Val' : np.random.randn(len(rng))}) 
    second_df['Type'] = 'B'
    
    final_df =  pd.concat([first_df,second_df]).sort_values(by = 'Date')
    final_df['Is_Weekend'] = np.where((final_df['Date'].dt.weekday == 5), 1, 0 )
    
    final_df['Val_2'] = final_df['Val'] * 3
    final_df['Diff'] = final_df['Val'] - final_df['Val_2']
    
    A_df = final_df[final_df['Type']=='A']
    B_df = final_df[final_df['Type']=='B']
    
    fig = make_subplots(rows=2, cols=1,
                        vertical_spacing = 0.05,
                        shared_xaxes=True)
    fig.add_trace(go.Scatter(
        x = A_df['Date'], 
        y = A_df['Val'],
        customdata = A_df['Diff'],
        hovertemplate = '%{y:$}<br>Diff:%{customdata:$}',
        fill=None,
        mode='lines+markers',
        line_color='orange', showlegend=True, name = "Val_Yellow"),
                row = 1, col = 1)
    fig.add_trace(go.Scatter(
        x =  A_df['Date'], 
        y = A_df['Val_2'],
        fill='tonexty', # fill area
        mode='lines+markers', line_color='red', showlegend=False, name ="Val_2"),
                row = 1, col = 1)
    fig.update_xaxes(showgrid=False, row=1, col=1)
    
    
    fig.add_trace(go.Scatter(
        x = B_df['Date'], 
        y = B_df['Val'],
        customdata = B_df['Diff'],
        hovertemplate = '%{y:$}<br>Diff:%{customdata:$}',
        fill=None,
        mode='lines+markers',
        line_color='blue', showlegend=True, name = "Val_Blue"),
                row = 2, col = 1)
    
    fig.add_trace(go.Scatter(
        x =  B_df['Date'], 
        y = B_df['Val_2'],
        fill='tonexty', # fill area
        mode='lines+markers', line_color='red', showlegend=True, name ="Val_2"),
                row = 2, col = 1)
    
    fig.update_yaxes(tickprefix = "$")
    
    fig.update_layout(hovermode='x unified', xaxis_range=[A_df['Date'].iloc[0], A_df['Date'].iloc[len(A_df)-1]])
    

    enter image description here