2

I have a dataset , df, where I am trying to modify and add some additional text to the already established hover text.

Here is the data:

   POD       Start      End         Diff        Percent     Date        
    IAD     4/1/2019    5/1/2019    160.4279    11.10809    04-01-2019 to 05-01-2019
    IAD     5/1/2019    6/1/2019    136.0248    8.476798    05-01-2019 to 06-01-2019
    IAD     6/1/2019    7/1/2019    174.0513    9.998946    06-01-2019 to 07-01-2019
    IAD     7/1/2019    8/1/2019    112.0424    5.851551    07-01-2019 to 08-01-2019
    IAD     8/1/2019    9/1/2019    141.8488    6.998691    08-01-2019 to 09-01-2019
    IAD     9/1/2019    10/1/2019   103.5522    4.774984    09-01-2019 to 10-01-2019
    IAD     10/1/2019   11/1/2019   125.6087    5.528085    10-01-2019 to 11-01-2019
    IAD     11/1/2019   12/1/2019   145.2591    6.058016    11-01-2019 to 12-01-2019
    IAD     12/1/2019   1/1/2020    115.5121    4.542251    12-01-2019 to 01-01-2020
    IAD     1/1/2020    2/1/2020    185.7191    6.985673    01-01-2020 to 02-01-2020
    IAD     2/1/2020    3/1/2020    126.7386    4.455896    02-01-2020 to 03-01-2020
    IAD     3/1/2020    4/1/2020    231.3461    7.786734    03-01-2020 to 04-01-2020
    IAD     4/1/2020    5/1/2020    97.02587      3.02981   04-01-2020 to 05-01-2020
    IAD     5/1/2020    6/1/2020    42.85235      1.298792  05-01-2020 to 06-01-2020
    IAD     6/1/2020    7/1/2020    124.666    3.729997     06-01-2020 to 07-01-2020
    IAD     7/1/2020    8/1/2020    357.9974    10.32609    07-01-2020 to 08-01-2020
    IAD     8/1/2020    9/1/2020    490.9587      12.8358   08-01-2020 to 09-01-2020
    IAD     9/1/2020    10/1/2020   204.5478    4.739428    09-01-2020 to 10-01-2020
    IAD     10/1/2020   11/1/2020   287.6025    6.362292    10-01-2020 to 11-01-2020
   SJCtest  4/1/2019    5/1/2019    12.38486    5.780551    04-01-2019 to 05-01-2019
   SJCtest  5/1/2019    6/1/2019    -2.61735    -1.15487    05-01-2019 to 06-01-2019
   SJCtest  6/1/2019    7/1/2019    -5.6187    -2.50814     06-01-2019 to 07-01-2019
   SJCtest  7/1/2019    8/1/2019    3.204252    1.467153    07-01-2019 to 08-01-2019
   SJCtest  8/1/2019    9/1/2019    -25.3782    -11.4521    08-01-2019 to 09-01-2019
   SJCtest  9/1/2019    10/1/2019   -10.9717    -5.59137    09-01-2019 to 10-01-2019

Here is the code: (A SO member has assisted me with this code)

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

df = pd.read_csv("df.csv")

fig = px.line(df, x="Date", y="Diff", color = 'POD')

import plotly.graph_objects as go
included = 0

lim = {'IAD': {'lower': 90,'upper': 350, 'color':'yellow'},
       'SJCtest': {'lower': 10,'upper': 12, 'color':'green'}}

for i, d in enumerate(fig.data):
    for j, y in enumerate(d.y):
        if y < lim[d.name]['lower'] or y > lim[d.name]['upper']:
             
             if j == 0:
                fig.add_traces(go.Scatter(x=[fig.data[i]['x'][j]],
                                          y=[fig.data[i]['y'][j]],
                                          mode = 'markers',
                                          marker = dict(color=lim[d.name]['color']),
                                          name = d.name + ' threshold',
                                          legendgroup = d.name + ' threshold'))
                included = included + 1
             else:
                fig.add_traces(go.Scatter(x=[fig.data[i]['x'][j-1], fig.data[i]['x'][j]],
                                          y=[fig.data[i]['y'][j-1], fig.data[i]['y'][j]],
                                          mode = 'lines',
                                          # marker = dict(color='yellow'),
                                          line = dict(width = 6, color = lim[d.name]['color']),
                                          name = d.name + ' threshold',
                                          legendgroup = d.name + ' threshold',
                                          showlegend = False if included > 0 else True,
                                         ))
                included = included + 1
            
fig.show()

Here is the visualization

enter image description here

This looks great, but I wish to add some additional lines to the hover text such as text that appears like this:

          POD:   IAD
          Date:  ....(the appropriate date)
          Percent: ...(the appropriate percent value)

I have read the documentation and have tried to implement the:

 fig = (hover_name="", hover_data=["", ""]

I am not getting the correct result. Any suggestion is appreciated.

2 Answers 2

2

Try these steps:

- Add the parameter hover_data to your fig when calling px.line:

fig = px.line(df, x="Date", y="Diff", color = 'POD', hover_data=['POD','Date','Percent'])

- Add the parameter customdata = fig.data[i].customdata to both of your go.Scatter calls.

- Define your desired hover template:

template = """
<b>POD:</b> %{customdata[0]}<br>
<b>Date:</b> %{x}<br>
<b>Percent:</b> %{customdata[2]:.2f}%
<extra></extra>
"""

- Finally, you can change the hovertemplate with:

fig.update_traces(hovertemplate=template)

Hope it works.


The whole code would be like this:

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

df = pd.read_csv("df.csv")

fig = px.line(df, x="Date", y="Diff", color = 'POD', hover_data=['POD','Date','Percent']) # modified line

included = 0

lim = {'IAD': {'lower': 90,'upper': 350, 'color':'yellow'},
       'SJCtest': {'lower': 10,'upper': 12, 'color':'green'}}

for i, d in enumerate(fig.data):
    for j, y in enumerate(d.y):
        if y < lim[d.name]['lower'] or y > lim[d.name]['upper']:
             
            if j == 0:
                fig.add_traces(go.Scatter(x=[fig.data[i]['x'][j]],
                                          y=[fig.data[i]['y'][j]],
                                          customdata = fig.data[i].customdata, # newline
                                          mode = 'markers',
                                          marker = dict(color=lim[d.name]['color']),
                                          name = d.name + ' threshold',
                                          legendgroup = d.name + ' threshold'))
                included = included + 1
            else:
                fig.add_traces(go.Scatter(x=[fig.data[i]['x'][j-1], fig.data[i]['x'][j]],
                                          y=[fig.data[i]['y'][j-1], fig.data[i]['y'][j]],
                                          mode = 'lines',
                                          customdata = fig.data[i].customdata, # newline
                                          # marker = dict(color='yellow'),
                                          line = dict(width = 6, color = lim[d.name]['color']),
                                          name = d.name + ' threshold',
                                          legendgroup = d.name + ' threshold',
                                          showlegend = False if included > 0 else True,
                                         ))
                included = included + 1

# custom template
template = """
<b>POD:</b> %{customdata[0]}<br>
<b>Date:</b> %{x}<br>
<b>Percent:</b> %{customdata[2]:.2f}%
<extra></extra>
"""
fig.update_traces(hovertemplate=template) #newline
fig.show()
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you so much @Caina - I can place this particular code anywhere right? (As long as it is not within a loop?)
Sorry @Lynnette, I think I don't understand your question very well... For sure you can specify hover_data when creating a plot with plotly.express and use update_traces(hovertemplate=template) to specify your desired hover template outside a loop. But for customdata in this particular case, it needs to be inside the loop to achieve your purpose.
I'm practicing and learning plotly as well. When it gets too complicated, I just modify the values directly inside fig.data as you did, once it has a well-organized and accessible structure.
Ok! I've added the whole modified code to make it easier. Hope it works!
Thank you! I will try this soon! Thank you
1

Just inlclude the following in fig.add_traces(go.Scatter() when you're adding your highlighted series:

hovertemplate = 'POD='+d.name+'<br>Date=%{x}<br>Diff=%{y}<extra></extra>'

Plot

enter image description here

Complete code:

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

df = pd.DataFrame({'POD': {0: 'IAD',
                          1: 'IAD',
                          2: 'IAD',
                          3: 'IAD',
                          4: 'IAD',
                          5: 'IAD',
                          6: 'IAD',
                          7: 'IAD',
                          8: 'IAD',
                          9: 'IAD',
                          10: 'IAD',
                          11: 'IAD',
                          12: 'IAD',
                          13: 'IAD',
                          14: 'IAD',
                          15: 'IAD',
                          16: 'IAD',
                          17: 'IAD',
                          18: 'IAD',
                          19: 'SJCtest',
                          20: 'SJCtest',
                          21: 'SJCtest',
                          22: 'SJCtest',
                          23: 'SJCtest',
                          24: 'SJCtest'},
                         'Start': {0: '4/1/2019',
                          1: '5/1/2019',
                          2: '6/1/2019',
                          3: '7/1/2019',
                          4: '8/1/2019',
                          5: '9/1/2019',
                          6: '10/1/2019',
                          7: '11/1/2019',
                          8: '12/1/2019',
                          9: '1/1/2020',
                          10: '2/1/2020',
                          11: '3/1/2020',
                          12: '4/1/2020',
                          13: '5/1/2020',
                          14: '6/1/2020',
                          15: '7/1/2020',
                          16: '8/1/2020',
                          17: '9/1/2020',
                          18: '10/1/2020',
                          19: '4/1/2019',
                          20: '5/1/2019',
                          21: '6/1/2019',
                          22: '7/1/2019',
                          23: '8/1/2019',
                          24: '9/1/2019'},
                         'End': {0: '5/1/2019',
                          1: '6/1/2019',
                          2: '7/1/2019',
                          3: '8/1/2019',
                          4: '9/1/2019',
                          5: '10/1/2019',
                          6: '11/1/2019',
                          7: '12/1/2019',
                          8: '1/1/2020',
                          9: '2/1/2020',
                          10: '3/1/2020',
                          11: '4/1/2020',
                          12: '5/1/2020',
                          13: '6/1/2020',
                          14: '7/1/2020',
                          15: '8/1/2020',
                          16: '9/1/2020',
                          17: '10/1/2020',
                          18: '11/1/2020',
                          19: '5/1/2019',
                          20: '6/1/2019',
                          21: '7/1/2019',
                          22: '8/1/2019',
                          23: '9/1/2019',
                          24: '10/1/2019'},
                         'Diff': {0: 160.4279,
                          1: 136.0248,
                          2: 174.0513,
                          3: 112.0424,
                          4: 141.8488,
                          5: 103.5522,
                          6: 125.6087,
                          7: 145.2591,
                          8: 115.5121,
                          9: 185.7191,
                          10: 126.7386,
                          11: 231.3461,
                          12: 97.02587,
                          13: 42.85235,
                          14: 124.666,
                          15: 357.9974,
                          16: 490.9587,
                          17: 204.5478,
                          18: 287.6025,
                          19: 12.38486,
                          20: -2.61735,
                          21: -5.6187,
                          22: 3.204252,
                          23: -25.3782,
                          24: -10.9717},
                         'Percent': {0: 11.108089999999999,
                          1: 8.476797999999999,
                          2: 9.998946,
                          3: 5.851551000000001,
                          4: 6.998691,
                          5: 4.774984,
                          6: 5.528085,
                          7: 6.058016,
                          8: 4.542251,
                          9: 6.985672999999999,
                          10: 4.455896,
                          11: 7.786734,
                          12: 3.02981,
                          13: 1.298792,
                          14: 3.729997,
                          15: 10.326089999999999,
                          16: 12.8358,
                          17: 4.739428,
                          18: 6.362292,
                          19: 5.780551,
                          20: -1.15487,
                          21: -2.50814,
                          22: 1.4671530000000002,
                          23: -11.4521,
                          24: -5.5913699999999995},
                         'Date': {0: '04-01-2019 to 05-01-2019',
                          1: '05-01-2019 to 06-01-2019',
                          2: '06-01-2019 to 07-01-2019',
                          3: '07-01-2019 to 08-01-2019',
                          4: '08-01-2019 to 09-01-2019',
                          5: '09-01-2019 to 10-01-2019',
                          6: '10-01-2019 to 11-01-2019',
                          7: '11-01-2019 to 12-01-2019',
                          8: '12-01-2019 to 01-01-2020',
                          9: '01-01-2020 to 02-01-2020',
                          10: '02-01-2020 to 03-01-2020',
                          11: '03-01-2020 to 04-01-2020',
                          12: '04-01-2020 to 05-01-2020',
                          13: '05-01-2020 to 06-01-2020',
                          14: '06-01-2020 to 07-01-2020',
                          15: '07-01-2020 to 08-01-2020',
                          16: '08-01-2020 to 09-01-2020',
                          17: '09-01-2020 to 10-01-2020',
                          18: '10-01-2020 to 11-01-2020',
                          19: '04-01-2019 to 05-01-2019',
                          20: '05-01-2019 to 06-01-2019',
                          21: '06-01-2019 to 07-01-2019',
                          22: '07-01-2019 to 08-01-2019',
                          23: '08-01-2019 to 09-01-2019',
                          24: '09-01-2019 to 10-01-2019'}})

fig = px.line(df, x="Date", y="Diff", color = 'POD')

import plotly.graph_objects as go
included = 0

lim = {'IAD': {'lower': 90,'upper': 350, 'color':'yellow'},
       'SJCtest': {'lower': 10,'upper': 12, 'color':'green'}}

for i, d in enumerate(fig.data):
    for j, y in enumerate(d.y):
        if y < lim[d.name]['lower'] or y > lim[d.name]['upper']:
             
             if j == 0:
                fig.add_traces(go.Scatter(x=[fig.data[i]['x'][j]],
                                          y=[fig.data[i]['y'][j]],
                                          mode = 'markers',
                                          marker = dict(color=lim[d.name]['color']),
                                          name = d.name + ' threshold',
                                          legendgroup = d.name + ' threshold',
                                          hovertemplate= 'POD=IAD<br>Date=%{x}<br>Percent=%{y}<extra></extra>'))
                included = included + 1
             else:
                fig.add_traces(go.Scatter(x=[fig.data[i]['x'][j-1], fig.data[i]['x'][j]],
                                          y=[fig.data[i]['y'][j-1], fig.data[i]['y'][j]],
                                          mode = 'lines',
                                          # marker = dict(color='yellow'),
                                          line = dict(width = 6, color = lim[d.name]['color']),
                                          name = d.name + ' threshold',
                                          legendgroup = d.name + ' threshold',
                                          showlegend = False if included > 0 else True,
                                          hovertemplate = 'POD='+d.name+'<br>Date=%{x}<br>Diff=%{y}<extra></extra>'
                                         ))
                included = included + 1
            
fig.show()

2 Comments

Hi @vestland I am wondering what does: showlegend = False if included > 0 else True, )) included = included + 1 mean. It is saying that the values will only show in the legend if included is greater than 0? I say this, because some of my values do not show in the legend because I have set the lower limit to 0. How would I fix that?
@Lynette I'm not 100% sure what you'd like to fix. But you are on the right track with regards to what included=included+1 does; it simply prevents the name of that particular trace to show up in the legend. One thing that's not too good about my chosen approach here, is that there's one trace added for each and every point that crosses the trehshold. But try and remove included=included+1 and see what happens. The rest of the plot should not be affected.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.