# Displaying edge labels of networkx graph in plotly

**URL:** <https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113>\
**Category:** 📊 Plotly Python\
**Created:** [May 8, 2020, 3:58pm UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113 "2020-05-08T15:58:00Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Natasha](https://avatars.discourse-cdn.com/v4/letter/n/df705f/32.png) [@Natasha](https://community.plotly.com/u/Natasha)\
**Post date:** [May 8, 2020, 3:58pm UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113/1 "2020-05-08T15:58:00Z")

</div>

I’m trying to display edge weights of Networkx graph while plotting using plotly. There is a problem in displaying the edge weights as edge labels while hovering over edges of the resulting plot.

Code:

```
import numpy as np
import networkx as nx
import plotly.graph_objects as go

from pprint import pprint
from collections import OrderedDict
from matplotlib import pyplot as plt

def get_edge_trace(G):
    edge_x = []
    edge_y = []

    etext = [f'weight{w}' for w in list(nx.get_edge_attributes(G, 'diameter').values())]

    for edge in G.edges():
        x0, y0 = G.nodes[edge[0]]['pos']
        x1, y1 = G.nodes[edge[1]]['pos']
        edge_x.append(x0)
        edge_x.append(x1)
        edge_x.append(None)
        edge_y.append(y0)
        edge_y.append(y1)
        edge_y.append(None)

    edge_trace = go.Scatter(
        x=edge_x, y=edge_y,
        line=dict(width=0.5, color='#888'),
        marker=dict(color='rgb(125,125,125)', size=1),
        text=etext,
        hoverinfo='text',
        mode='lines' # lines
    )

    return edge_trace

def get_node_trace(G):
    node_x = []
    node_y = []
    for node in G.nodes():
        x, y = G.nodes[node]['pos']
        node_x.append(x)
        node_y.append(y)

    node_trace = go.Scatter(
        x=node_x, y=node_y,
        mode='markers',
        hoverinfo='text',
        marker=dict(
            showscale=True,
            # colorscale options
            # 'Greys' | 'YlGnBu' | 'Greens' | 'YlOrRd' | 'Bluered' | 'RdBu' |
            # 'Reds' | 'Blues' | 'Picnic' | 'Rainbow' | 'Portland' | 'Jet' |
            # 'Hot' | 'Blackbody' | 'Earth' | 'Electric' | 'Viridis' |
            colorscale='YlGnBu',
            reversescale=True,
            color=[],
            size=10,
            colorbar=dict(
                thickness=15,
                title='Node Connections',
                xanchor='left',
                titleside='right'
            ),
            line_width=2))

    return node_trace

if __name__ == ' __main__':

    tail = [1, 2, 3]
    head = [2, 3, 4]

    xpos = [0, 1, 2, 3]
    ypos = [0, 0, 0, 0]
    w = [1, 2, 3]
    xpos_ypos = [(x, y) for x, y in zip(xpos, ypos)]

    ed_ls = [(x, y) for x, y in zip(tail, head)]
    G = nx.OrderedGraph()
    G.add_edges_from(ed_ls)

    pos = OrderedDict(zip(G.nodes, xpos_ypos))
    edge_w = OrderedDict(zip(G.edges, w))

    nx.draw(G, pos=pos, with_labels=True)
    nx.set_node_attributes(G, pos, 'pos')
    nx.set_edge_attributes(G, edge_w, 'weight')
    plt.show()

    # convert to plotly graph
    edge_trace = get_edge_trace(G)
    node_trace = get_node_trace(G)
    pprint(np.array(nx.get_edge_attributes(G, 'diameter').values()))
    pprint(edge_trace)
    pprint(node_trace)

    fig = go.Figure(data=[edge_trace, node_trace],
                    layout=go.Layout(
                        title='<br>Network graph made with Python',
                        titlefont_size=16,
                        showlegend=False,
                        hovermode='closest',
                        margin=dict(b=20, l=5, r=5, t=40),
                        annotations=[dict(
                            text="Python code: <a href='https://plot.ly/ipython-notebooks/network-graphs/'> https://plot.ly/ipython-notebooks/network-graphs/</a>",
                            showarrow=False,
                            xref="paper", yref="paper",
                            x=0.005, y=-0.002)],
                        xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
                        yaxis=dict(showgrid=False, zeroline=False, showticklabels=False))
                    )
    fig.write_html('plot.html', auto_open=True)

```

The edge weights aren’t displayed for some reason while hovering over edges. I’ve added edge text n get\_edge\_trace function.

Could someone help me out?

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [May 8, 2020, 5:40pm UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113/2 "2020-05-08T17:40:02Z")

</div>

Hi @Natasha,

Plotly associates a text to a position of coordinates (x, y). An edge is not defined by a unique point to assign it a text.  
In order to display the edge weights you can define one more scatter trace, of `mode='text'`, and its x, y lists are the middle point coordinates of the edges.  
For your example the marker colorscale and colorbar in the `node_trace` definition should be removed, because marker color is not defined as a numerical list (it is empty).

This is the code that displays the edge weights. I defined synthetical weights because your `etext` is an empty list.

```auto
import numpy as np
import networkx as nx
import plotly.graph_objects as go
from collections import OrderedDict

def get_edge_trace(G):
    edge_x = []
    edge_y = []

    etext = [f'weight{w}' for w in list(nx.get_edge_attributes(G, 'diameter').values())]#THIS list is empty for your data
    xtext=[]
    ytext=[]
    for edge in G.edges():

        x0, y0 = G.nodes[edge[0]]['pos']
        x1, y1 = G.nodes[edge[1]]['pos']
        xtext.append((x0+x1)/2)
        ytext.append((y0+y1)/2)
        edge_x.append(x0)
        edge_x.append(x1)
        edge_x.append(None)
        edge_y.append(y0)
        edge_y.append(y1)
        edge_y.append(None)

    edge_trace = go.Scatter(
        x=edge_x, y=edge_y,
        line=dict(width=0.5, color='#888'),
        mode='lines'
    )
    eweights_trace = go.Scatter(x=xtext,y= ytext, mode='text',
                              marker_size=0.5,
                              text=[0.45, 0.7, 0.34],
                              textposition='top center',
                              hovertemplate='weight: %{text}<extra></extra>')
    return edge_trace, eweights_trace

def get_node_trace(G):
    node_x = []
    node_y = []
    for node in G.nodes():
        x, y = G.nodes[node]['pos']
        node_x.append(x)
        node_y.append(y)

    node_trace = go.Scatter(
        x=node_x, y=node_y,
        mode='markers',
        marker_size=12,
        #hoverinfo='text', #THIS LINE HAS NO SENSE BECAUSE text WAS NOT DEFINED
        marker_color='RoyalBlue',
        )

    return node_trace

if __name__ == ' __main__':

    tail = [1, 2, 3]
    head = [2, 3, 4]

    xpos = [0, 1, 2, 3]
    ypos = [0, 0, 0, 0]
    w = [1, 2, 3]
    xpos_ypos = [(x, y) for x, y in zip(xpos, ypos)]

    ed_ls = [(x, y) for x, y in zip(tail, head)]
    G = nx.OrderedGraph()
    G.add_edges_from(ed_ls)

    pos = OrderedDict(zip(G.nodes, xpos_ypos))
    edge_w = OrderedDict(zip(G.edges, w))
    nx.set_node_attributes(G, pos, 'pos')
    nx.set_edge_attributes(G, edge_w, 'weight')

    # convert to plotly graph
    edge_trace, eweights_trace = get_edge_trace(G)
    node_trace = get_node_trace(G)

    fig = go.Figure(data=[edge_trace, node_trace,eweights_trace],
                    layout=go.Layout(
                        title='<br>Network graph made with Python',
                        titlefont_size=16,
                        showlegend=False,
                        hovermode='closest',
                        margin=dict(b=20, l=5, r=5, t=40),
                        xaxis_visible=False,
                        yaxis_visible=False)
                    )

```

Note that in the definition of `eweight_trace`, `textposition` can be a list with one of the following positions:

```auto
 ( "top left" | "top center" | "top right" | "middle left" | "middle center" | "middle right" | "bottom left" | "bottom center" | "bottom right" )

```

---

<div class="post-metadata">

**Author:** ![Natasha](https://avatars.discourse-cdn.com/v4/letter/n/df705f/32.png) [@Natasha](https://community.plotly.com/u/Natasha)\
**Post date:** [May 9, 2020, 6:32am UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113/3 "2020-05-09T06:32:37Z")

</div>

@empet Thanks a lot. Could you please explain how to add the node labels here? For instance, I want to use node numbers as node labels. Also, I’d like to know how to view the edge weights only when I hover over a given edge. I don’t want the text to be displayed by default.

---

<div class="post-metadata">

**Author:** ![Natasha](https://avatars.discourse-cdn.com/v4/letter/n/df705f/32.png) [@Natasha](https://community.plotly.com/u/Natasha)\
**Post date:** [May 9, 2020, 6:59am UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113/4 "2020-05-09T06:59:41Z")

</div>

> [@Natasha](#):
>
> Also, I’d like to know how to view the edge weights only when I hover over a given edge. I don’t want the text to be displayed by default.

I could do this by changing mode=‘lines’ in eweights\_trace.

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [May 9, 2020, 8:56am UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113/5 "2020-05-09T08:56:58Z")

</div>

@Natasha

Define the corresponding trace like this:

```auto
eweights_trace = go.Scatter(x=xtext,y= ytext, 
                              mode='markers',
                              marker_size=0.5,
                              text=[0.45, 0.7, 0.34],
                              #textposition='top center',
                              hovertemplate='weight: %{text}<extra></extra>')

```

i.e.change the `mode` from `'text`` to `'markers’`, and remove `textposition`.

---

<div class="post-metadata">

**Author:** ![Natasha](https://avatars.discourse-cdn.com/v4/letter/n/df705f/32.png) [@Natasha](https://community.plotly.com/u/Natasha)\
**Post date:** [May 9, 2020, 10:09am UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113/6 "2020-05-09T10:09:46Z")

</div>

@empet

> [@Natasha](#):
>
> Could you please explain how to add the node labels here? For instance, I want to use node numbers as node labels

Could you please suggest how this can be done?

---

<div class="post-metadata">

**Author:** ![Natasha](https://avatars.discourse-cdn.com/v4/letter/n/df705f/32.png) [@Natasha](https://community.plotly.com/u/Natasha)\
**Post date:** [May 9, 2020, 11:32am UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113/7 "2020-05-09T11:32:46Z")

</div>

@empet

I tried this

```auto
nlabels_trace = go.Scatter(x=node_x,
                                y=node_y,
                                mode='markers',
                                marker_size=0.5,
                                text=[1, 2, 3, 4],
                                # textposition='top center',
                                hovertemplate='node: %{text}<extra></extra>')

```

Unfortunately, it didn’t work.

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [May 9, 2020, 11:40am UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113/8 "2020-05-09T11:40:36Z")

</div>

@Natasha  
Meanwhile I tried to find out why your Plotly figure was different from that drawn with networkx. I noticed that you labeled the nodes in the Excel file starting with 1, but Plotly code supposed that nodes are labeled from 0. So there was a nonconcordance between node labels and edge end labels. Moreover, I’m wondering why you defined a networkx graph as long as your Excel file contained all information to draw a Plotly network.

Only when you cannot provide the node positions you have to define first a networkx graph and set a graph layout to place the nodes in the plane, i.e. to assign them a position (expressed by node coordinates).

Here is a new code that resulted by modifying data from your Excel file to get the right Plotly network and avoiding the use of networkx. Moreover I assigned the node indices as labels:

```auto
import numpy as np
import pandas as pd
import plotly.graph_objects as go

def get_plotly_data(E, coords):

   # E is the list of tuples representing the graph edges
    # coords is the list of node coordinates 
    N = len(coords)
    Xnodes = [coords[k][0] for k in range(N)] # x-coordinates of nodes
    Ynodes = [coords[k][1] for k in range(N)] # y-coordnates of nodes

    Xedges = []
    Yedges = []
    Xweights = []
    Yweights = []
    for e in E:
        x0, x1 = coords[e[0]][0], coords[e[1]][0]
        y0, y1 = coords[e[0]][1], coords[e[1]][1]
        Xedges.extend([x0, x1, None])
        Yedges.extend([y0, y1, None])
        Xweights.append((x0+x1)/2)
        Yweights.append((y0+y1)/2)
    return Xnodes, Ynodes, Xedges, Yedges, Xweights, Yweights 

def get_node_trace(x, y, labels, marker_size=10, marker_color='RoyalBlue', 
                   line_color='rgb(50,50,50)', line_width=0.5):
    return go.Scatter(
                x=x,
                y=y,
                mode='markers',
                marker=dict(
                            size=marker_size, 
                            color=marker_color,
                            line=dict(color=line_color, width=line_width)
                             ),
            text=labels,
            hoverinfo='text'
               )

def get_edge_trace(x, y, line_color='#888', line_width=1):
    return go.Scatter(
                x=x,
                y=y,
                mode='lines',
                line_color=line_color,
                line_width=line_width,
                hoverinfo='none'
               )

df = pd.read_excel(open("file.xlsx", 'rb'), sheet_name=0, index=False)

#df.columns

I = np.where(np.isnan(df['node'].values))[0]
print(I)

#Reindex the nodes, tail and head, starting with 0

t = df['t'].values-1
h = df['h'].values-1
node= df['node'].values.astype(int)[:I[0]]-1

coords = [(xc,yc ) for xc, yc in zip(df['x'][:I[0]], df['y'][:I[0]])]
E = list(zip(t, h)) #the graph edges
print(E[:5])

Xn, Yn, Xe, Ye, Xw, Yw = get_plotly_data(E, coords)

node_trace = get_edge_trace(Xe, Ye)
edge_trace = get_node_trace(Xn, Yn, node)
eweights_trace = go.Scatter(x=Xw, y= Yw, 
                            mode='markers',
                            marker_size=0.5,
                            text=df['d'][:I[0]],
                            hovertemplate='weight: %{text}<extra></extra>')

layout=go.Layout(title_text='Your title',
            title_x=0.5,
                 height=800,
            showlegend=False,
            xaxis_visible=False,
            yaxis_visible=False,   
            margin=dict(b=20, l=5, r=5, t=80),     
            hovermode='closest')
fig = go.Figure(data=[edge_trace, node_trace, eweights_trace], layout=layout)

```

---

<div class="post-metadata">

**Author:** ![Natasha](https://avatars.discourse-cdn.com/v4/letter/n/df705f/32.png) [@Natasha](https://community.plotly.com/u/Natasha)\
**Post date:** [May 9, 2020, 12:06pm UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113/9 "2020-05-09T12:06:43Z")

</div>

@empet

Thanks a lot for the response on the other post. Actually, I did `pos = OrderedDict(zip(sorted(G.nodes), xpos_ypos))` and that solved my problem. I’m not really sure how this solved the indexing problem that you are referring to.

I was using Network for the same reason that you mentioned. To get the positions when I don’t have the coordinates. I like the alternate code presented by you. Thanks!

Regarding the node labels,  
I could view those now. But the coordinates of nodes that were displayed earlier is missing now. How do I retain both the (x,y) coordinate display of nodes and node label?

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [May 9, 2020, 12:57pm UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113/10 "2020-05-09T12:57:14Z")

</div>

@Natasha  
To display both label and coords, set in the definition of the function `get_node_trace()`

`mode='markers'`

and

`hoverinfo='text+x+y'`

---

<div class="post-metadata">

**Author:** ![Natasha](https://avatars.discourse-cdn.com/v4/letter/n/df705f/32.png) [@Natasha](https://community.plotly.com/u/Natasha)\
**Post date:** [May 9, 2020, 1:00pm UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113/11 "2020-05-09T13:00:51Z")

</div>

@empet

Thank you. But, is there an option to add two node labels ?

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [May 9, 2020, 1:10pm UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113/12 "2020-05-09T13:10:29Z")

</div>

Yes,  
for a graph with 5 nodes of id 0, 1, 2, 3, 4, and labels as below:

```auto
node= np.arange(5)
secondary_label=[' A', ' B', 'C', 'D', 'E']

```

define in `node_trace`:

```auto
text= [f'node id: {n}<br>label: {sl}' for n, sl in zip(node, secondary_label)]

```

`<br>` is html tag for newline.

---

<div class="post-metadata">

**Author:** ![Natasha](https://avatars.discourse-cdn.com/v4/letter/n/df705f/32.png) [@Natasha](https://community.plotly.com/u/Natasha)\
**Post date:** [May 10, 2020, 5:46am UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113/14 "2020-05-10T05:46:39Z")

</div>

@empet  
Hi,

While hovering over the nodes , I could click on a node and display the label. But when a second node is clicked, the label of the first node disappears.

Is there a way to display a node label on clicking it and remove the label while clicking on the same node for the second time?

Thanks a lot

---

<div class="post-metadata">

**Author:** ![Natasha](https://avatars.discourse-cdn.com/v4/letter/n/df705f/32.png) [@Natasha](https://community.plotly.com/u/Natasha)\
**Post date:** [October 25, 2020, 2:22pm UTC](https://community.plotly.com/t/displaying-edge-labels-of-networkx-graph-in-plotly/39113/15 "2020-10-25T14:22:40Z")

</div>

@empet  
Could you please have a look at this [Plot 3D network graph](https://community.plotly.com/t/plot-3d-network-graph/46442) post?
