# Update second graph while hovering on first graph

**URL:** https://community.plotly.com/t/update-second-graph-while-hovering-on-first-graph/73725
**Category:** Dash Python
**Created:** [March 20, 2023, 1:19pm UTC](https://community.plotly.com/t/update-second-graph-while-hovering-on-first-graph/73725 "2023-03-20T13:19:10Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![DeLaRiva](https://avatars.discourse-cdn.com/v4/letter/d/ce73a5/32.png) [@DeLaRiva](https://community.plotly.com/u/DeLaRiva)
#### Post date: [March 20, 2023, 1:19pm UTC](https://community.plotly.com/t/update-second-graph-while-hovering-on-first-graph/73725/1 "2023-03-20T13:19:10Z")

</div>

I’m trying to implement the very same feature that hovering on one graph results in a separate plot as on [Part 4. Interactive Graphing and Crossfiltering | Dash for Python Documentation | Plotly](https://dash.plotly.com/interactive-graphing#update-graphs-on-hover)

However, as the example is rather extend I’m not sure whether it’s correct what I did and/or what is not.

So far, I have:

```auto
df2 = all_df.melt(id_vars=['Device','time', 'Path'], value_vars=['V+','V-','I_A', 'I_fil'])
df2['path'] = df2['Path']

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash( __name__ , title='Dashboard', external_stylesheets=external_stylesheets)             

colors = {
        'background': '#000000',
        'text': '#f3ff00'
        }

app.layout = html.Div(
                    children = [
    
                            html.Div([
                                    html.H4('Dauertest'),
                                    html.Div(children = ""),

                                    dcc.Graph(id = 'General' 
                                              , figure={}
                                              ),

                                    dcc.RadioItems(
                                                  id="signals",
                                                  options = ['V+', 'V-', 'I_A', 'I_fil'],
                                                  value = 'V+',
                                                  inline=True
                                                  ),
                                    
                                    dcc.Graph(id = 'Zoomed' 
                                              ),
                                    html.Br(),
                                    ]),
])

@app.callback(
              Output("General", "figure"), 
              Input("signals", "value")
              )
def update_scatter_chart(signals):
    df3 = df2.query('variable==@signals').groupby('path').first() 

    fig_general = px.scatter(df3
                              , x = "time"
                              , y = 'value'
                              , custom_data = ['Path']
                              , color = 'Device'
                              , symbol = 'variable'
                              , hover_name = "Device"
                              , opacity = 0.6
                              , template = 'plotly_dark'
                              , marginal_y = "rug"
                              )
    fig_general.update_layout(
                              transition_duration = 500
                              , autosize = True
                              , height = 700
                              , hovermode = 'closest'
                              )
    fig_general.update_traces(marker = dict(
                                            size = 14
                                            )
                              )
    return fig_general

def update_zoom_chart(df5):
    
    fig_zoom = px.scatter(df5
                              , x = "time"
                              , y = 'value'
                              , color = 'Device'
                              , symbol = 'variable'
                              , hover_name = "Device"
                              , opacity = 0.6
                              , template = 'plotly_dark'
                              )
    fig_zoom.update_layout(
                              transition_duration = 500
                              , autosize = True
                              , height = 500
                              )

    return fig_zoom

@app.callback(
              Output("Zoomed", "figure"), 
              Input('General', 'hoverData')
              )
def update_hover(hoverData):
    path = hoverData['points'][0]['customdata']
    df5 = df2[df2['Path' == path]]
    return update_zoom_chart(df5)

```

At the moment I receive the error:

```auto
in update_hover
    path = hoverData['points'][0]['customdata']
TypeError: 'NoneType' object is not subscriptable

```

But according to the linked example I do not see the difference?

---

<div class="post-metadata">

### Author: ![hoatran](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/hoatran/32/21447_2.png) [@hoatran](https://community.plotly.com/u/hoatran)
#### Post date: [March 20, 2023, 1:59pm UTC](https://community.plotly.com/t/update-second-graph-while-hovering-on-first-graph/73725/2 "2023-03-20T13:59:53Z")

</div>

Can you provide dataframe too? And I think if you want to use `customdata` you should add `hover_data` in your fig.

---

<div class="post-metadata">

### Author: ![DeLaRiva](https://avatars.discourse-cdn.com/v4/letter/d/ce73a5/32.png) [@DeLaRiva](https://community.plotly.com/u/DeLaRiva)
#### Post date: [March 20, 2023, 2:42pm UTC](https://community.plotly.com/t/update-second-graph-while-hovering-on-first-graph/73725/3 "2023-03-20T14:42:58Z")

</div>

Sure, yes, it can be found on [Filebin | 2k1rbe9w0kh2au02](https://filebin.net/2k1rbe9w0kh2au02)  
The `Path` in the data is actually a really long string which reflects the source of the single data sets/excel files.

I thought with `custom_data` I’m addressing which data I’m going to use for updating the graph via hovering? Let’s say, I thought this is mandatory?

btw, meanwhile I figured out that

```auto
path = hoverData['points'][0]['customdata'][0]

```

creates a “better” error but yeah, it is still one 🙂

`ValueError: Value of 'custom_data_0' is not the name of a column in 'data_frame'. Expected one of ['Device', 'time', 'Path', 'variable', 'value'] but received: A1.xls`

It doesn’t look very off but yet I don’t know how to handle this one.

---

<div class="post-metadata">

### Author: ![hoatran](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/hoatran/32/21447_2.png) [@hoatran](https://community.plotly.com/u/hoatran)
#### Post date: [March 20, 2023, 3:22pm UTC](https://community.plotly.com/t/update-second-graph-while-hovering-on-first-graph/73725/4 "2023-03-20T15:22:19Z")

</div>

I think first of all you should change from `customdata` to `hovertext` because as I said if you want to use `customdata` you will have to set `hover_data` in `fig_general`. Second: You are returning `Device` name as `hover_name`, so I think you need to change from `df5 = df2[df2['Path' == path]]` to `df5=df2[df2['Device']==path]`. If you want to use Path, I think you need to change `hover_name`. Full code as below:

```auto
import dash
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
import pandas as pd
import plotly.express as px
from dash.exceptions import PreventUpdate
all_df = pd.read_csv('data.csv')

df2 = all_df.melt(id_vars=['Device','time', 'Path'], value_vars=['V+','V-','I_A', 'I_fil'])
df2['path'] = df2['Path']

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash( __name__ , title='Dashboard', external_stylesheets=external_stylesheets)             

colors = {
        'background': '#000000',
        'text': '#f3ff00'
        }

app.layout = html.Div(
                    children = [
    
                            html.Div([
                                    html.H4('Dauertest'),
                                    html.Div(children = ""),

                                    dcc.Graph(id = 'General' 
                                              , figure={}
                                              ),

                                    dcc.RadioItems(
                                                  id="signals",
                                                  options = ['V+', 'V-', 'I_A', 'I_fil'],
                                                  value = 'V+',
                                                  inline=True
                                                  ),
                                    
                                    dcc.Graph(id = 'Zoomed' 
                                              ),
                                    html.Br(),
                                    ]),
])

@app.callback(
              Output("General", "figure"), 
              Input("signals", "value")
              )
def update_scatter_chart(signals):
    df3 = df2.query('variable==@signals').groupby('path').first() 
    fig_general = px.scatter(df3
                              , x = "time"
                              , y = 'value'
                              , custom_data = ['Path']
                              , color = 'Device'
                              , symbol = 'variable'
                              , hover_name = "Device"
                              , opacity = 0.6
                              , template = 'plotly_dark'
                              , marginal_y = "rug"
                              )
    fig_general.update_layout(
                              transition_duration = 500
                              , autosize = True
                              , height = 700
                              , hovermode = 'closest'
                              )
    fig_general.update_traces(marker = dict(
                                            size = 14
                                            )
                              )
    return fig_general

def update_zoom_chart(df5):
    
    fig_zoom = px.scatter(df5
                              , x = "time"
                              , y = 'value'
                              , color = 'Device'
                              , symbol = 'variable'
                              , hover_name = "Device"
                              , opacity = 0.6
                              , template = 'plotly_dark'
                              )
    fig_zoom.update_layout(
                              transition_duration = 500
                              , autosize = True
                              , height = 500
                              )

    return fig_zoom

@app.callback(
              Output("Zoomed", "figure"), 
              Input('General', 'hoverData')
              )
def update_hover(hoverData):
    if hoverData:
        path = hoverData['points'][0]['hovertext']
        df5 = df2[df2['Device']== path]
        return update_zoom_chart(df5)
    else:
        raise PreventUpdate

if __name__ == " __main__":
    app.run_server(debug=False)

```

 ![Screenshot 2023-03-20 222300](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/a/c/aca3c175e146b04c89b5c0e522888d55aa8dca4c.png)

So if you want to use `Path` to update second graph, you can use below code:

```auto
import dash
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
import pandas as pd
import plotly.express as px
from dash.exceptions import PreventUpdate
all_df = pd.read_csv('data.csv')

df2 = all_df.melt(id_vars=['Device','time', 'Path'], value_vars=['V+','V-','I_A', 'I_fil'])
df2['path'] = df2['Path']

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash( __name__ , title='Dashboard', external_stylesheets=external_stylesheets)             

colors = {
        'background': '#000000',
        'text': '#f3ff00'
        }

app.layout = html.Div(
                    children = [
    
                            html.Div([
                                    html.H4('Dauertest'),
                                    html.Div(children = ""),

                                    dcc.Graph(id = 'General' 
                                              , figure={}
                                              ),

                                    dcc.RadioItems(
                                                  id="signals",
                                                  options = ['V+', 'V-', 'I_A', 'I_fil'],
                                                  value = 'V+',
                                                  inline=True
                                                  ),
                                    
                                    dcc.Graph(id = 'Zoomed' 
                                              ),
                                    html.Br(),
                                    ]),
])

@app.callback(
              Output("General", "figure"), 
              Input("signals", "value")
              )
def update_scatter_chart(signals):
    df3 = df2.query('variable==@signals').groupby('path').first() 
    fig_general = px.scatter(df3
                              , x = "time"
                              , y = 'value'
                              , custom_data = ['Path']
                              , color = 'Device'
                              , symbol = 'variable'
                              , hover_name = "Path"
                              , opacity = 0.6
                              , template = 'plotly_dark'
                              , marginal_y = "rug"
                              )
    fig_general.update_layout(
                              transition_duration = 500
                              , autosize = True
                              , height = 700
                              , hovermode = 'closest'
                              )
    fig_general.update_traces(marker = dict(
                                            size = 14
                                            )
                              )
    return fig_general

def update_zoom_chart(df5):
    
    fig_zoom = px.scatter(df5
                              , x = "time"
                              , y = 'value'
                              , color = 'Device'
                              , symbol = 'variable'
                              , hover_name = "Device"
                              , opacity = 0.6
                              , template = 'plotly_dark'
                              )
    fig_zoom.update_layout(
                              transition_duration = 500
                              , autosize = True
                              , height = 500
                              )

    return fig_zoom

@app.callback(
              Output("Zoomed", "figure"), 
              Input('General', 'hoverData')
              )
def update_hover(hoverData):
    if hoverData:
        path = hoverData['points'][0]['hovertext']
        df5 = df2[df2['Path']== path]
        return update_zoom_chart(df5)
    else:
        raise PreventUpdate

if __name__ == " __main__":
    app.run_server(debug=False, port=8054)

```

 ![Screenshot 2023-03-20 222526](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/6/e/6e58b9d90f02d29dacfe81ef14224611c942efd0.png)

---

<div class="post-metadata">

### Author: ![DeLaRiva](https://avatars.discourse-cdn.com/v4/letter/d/ce73a5/32.png) [@DeLaRiva](https://community.plotly.com/u/DeLaRiva)
#### Post date: [March 21, 2023, 7:47am UTC](https://community.plotly.com/t/update-second-graph-while-hovering-on-first-graph/73725/5 "2023-03-21T07:47:14Z")

</div>

Awesome, thank you very, very, very much!  
May I ask what exactly custom\_data and hover\_name are doing? Apparently, I misunderstood this.

However, is there a way to make the to updated graph show data already before hovering or clicking on a certain point? At the moment, when the dash board pops up, the graph is blank white until I hover over some data.  
I guess I have to define:

```auto
    dcc.Graph(id = 'Zoomed' 
                         , hoverData = {'points': [{'customdata': df2['path'][0]}]}
                      ),

```

but this here is not the way to go.  
Probably because I don’t understand how it is working, yet. Will see whether I can find comprehensive sources.

---

<div class="post-metadata">

### Author: ![hoatran](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/hoatran/32/21447_2.png) [@hoatran](https://community.plotly.com/u/hoatran)
#### Post date: [March 21, 2023, 8:28am UTC](https://community.plotly.com/t/update-second-graph-while-hovering-on-first-graph/73725/6 "2023-03-21T08:28:20Z")

</div>

I think you could update your callback as below:

```auto
@app.callback(
    Output("Zoomed", "figure"),
    Input('General', 'hoverData'))
def update_hover(hoverData):
    if hoverData:
        path = hoverData['points'][0]['hovertext']
        df5 = df2[df2['Path']== path]
        return update_zoom_chart(df5)
    else:
        
        df5 = df2[df2['Path']== df2['Path'].iloc[0]]
        return update_zoom_chart(df5)

```

---

<div class="post-metadata">

### Author: ![DeLaRiva](https://avatars.discourse-cdn.com/v4/letter/d/ce73a5/32.png) [@DeLaRiva](https://community.plotly.com/u/DeLaRiva)
#### Post date: [March 21, 2023, 8:55am UTC](https://community.plotly.com/t/update-second-graph-while-hovering-on-first-graph/73725/7 "2023-03-21T08:55:00Z")

</div>

You’re the best, thank you!
