Can you specify a bidirectional edge in a NetworkX digraph?

1.3k Views Asked by At

I'd like to be able to draw a NetworkX graph connecting characters from the movie "Love, Actually" (because it's that time of the year in this country), and specifying how each character "relates" to the other in the story.

Certain relationships between characters are unidirectional - e.g. Mark is in love with Juliet, but not the reverse. However, Mark is best friends with Peter, and Peter is best friends with Mark - this is a bidirectional relationship. Ditto Peter and Juliet being married to each other.

I'd like to specify both kinds of relationships. Using a NetworkX digraph in Python, I seem to have a problem: to specify a bidirectional edge between two nodes, I apparently have to provide the same link twice, which will subsequently create two arrows between two nodes.

What I'd really like is a single arrow connecting two nodes, with heads pointing both ways. I'm using NetworkX to create the graph, and pyvis.Network to render it in HTML.

Here is the code so far, which loads a CSV specifying the nodes and edges to create in the graph.

import networkx as nx
import csv
from pyvis.network import Network

dg = nx.DiGraph()
with open("rels.txt", "r") as fh:
    reader = csv.reader(fh)
    for row in reader:
        if len(row) != 3:
            continue     # Quick check for malformed csv input
        dg.add_edge(row[0], row[1], label=row[2])

nt = Network('500px', '800px', directed=True)
nt.from_nx(dg)
nt.show('nx.html', True)

Here is the CSV, which can be read as "Node1", "Node2", "Edge label":

Mark,Juliet,in love with
Mark,Peter,best friends
Peter,Mark,best friends
Juliet,Peter,married
Peter,Juliet,married

And the resulting image:

enter image description here

Whereas what I'd really like the graph to look like is this:

enter image description here

(Thank you to this site for the wonderful graph tool for the above visualisation)

Is there a way to achieve the above visualisation using NetworkX and Pyvis? I wasn't able to find any documentation on ways to create bidirectional edges in a directed graph.

1

There are 1 best solutions below

2
On

Read the csv into pandas. Create a digraph and plot. Networkx has quite a comprehensive documentation on plotting. See what I came up with

  import pandas as pd
import networkx as nx
from networkx import*

df =pd.DataFrame({'Source':['Mark','Mark','Peter','Juliet','Peter'],'Target':['Juliet','Peter','Mark','Peter','Juliet'],'Status':['in love with','best friends','best friends','married','married']})


#Create graph
g = nx.from_pandas_edgelist(df, 'Source', "Target", ["Status"],  create_using=nx.DiGraph())

pos = nx.spring_layout(g)

nx.draw(g, pos, with_labels=True)

edge_labels = dict([((n1, n2), d['Status'])
                    for n1, n2, d in g.edges(data=True)])

nx.draw_networkx_edge_labels(g, 
                             pos, edge_labels=edge_labels,
                             label_pos=0.5,
                             font_color='red', 
                             font_size=7, 
                             font_weight='bold',
                            verticalalignment='bottom' )

plt.show()

enter image description here