1

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.

Lou
  • 2,200
  • 2
  • 33
  • 66
  • For the suggested edit, "visualisation" is British English spelling, it's not incorrect grammar :) – Lou Dec 26 '22 at 18:30

1 Answers1

2

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

wwnde
  • 26,119
  • 6
  • 18
  • 32
  • Looks good! Just for completeness, which imports does this answer use? Helps future users who don't recognise the common abbreviations :) – Lou Dec 27 '22 at 08:44
  • 1
    Sorry, `import pandas as pd import networkx as nx from networkx import*` then read csv into pandas python library – wwnde Dec 27 '22 at 09:37