giorgioW
giorgioW

Reputation: 331

Represent relations between entities using python3

I want to represent a series of data using the networkx library for Python3 but I do not know how to approach the problem.

Basically I have a relation between two entities which is in a csv file called nations.csv. It looks like this:

China, Economicaid, Egypt
China, Economicaid, Indonesia
USSR, Economicaid, Cuba 
USSR, Economicaid, India
USSR, Economicaid, Poland
UK, Economicaid, India 
UK, Economicaid, Jordan
USA, Economicaid, Brazil

Understanding that the first row is one of the entity which is related to the third row (entity 2) between the second one:

relation

I've parsed the csv file in order to store each of the rows in a dictionary, as follows:

d = {}
d['entity1'] = []
d['relation'] = []
d['entity2'] = []

dictReader = csv.DictReader(open('nations.csv', 'rt'), fieldnames = 
['entity1', 'relation', 'entity2'], delimiter = ',', quotechar = '"')

for row in dictReader:
    for key in row:
        d[key].append(row[key])

What I've managed to do is plot the nodes using the function add_node() like the following example:

import csv
import networkx as nx
import matplotlib.pyplot as plt


d = {}
d['entity1'] = []
d['relation'] = []
d['entity2'] = []

dictReader = csv.DictReader(open('nations.csv', 'rt'), fieldnames = ['entity1', 'relation', 'entity2'], delimiter = ',', quotechar = '"')

for row in dictReader:
    for key in row:
        d[key].append(row[key])

print()

for i in range (1, len(d['entity1'])):
    r.append(d['entity1'][i])

for k in range (1, len(d['entity2'])):
    o.append(d['entity2'][k])


G=nx.Graph()

for j in range(len(r)):
    G.add_node(r[j])
    G.add_node(o[j])

nx.draw_networkx(G, with_labels = True, node_size = 500)

plt.show()

But the problem comes when I want to represent the edges between the nodes, because it is not only the edge itself, it also has its own label with the meaning.

Upvotes: 2

Views: 1325

Answers (1)

Paul Brodersen
Paul Brodersen

Reputation: 13031

Basically, the flag with_labels should really be called with_node_labels as it triggers only the plotting of the node labels. Hence you need to manually add the edge labels (networkx.draw_networkx_edge_labels) after having drawn the graph (networkx.draw`), and you need to 1) plot on the same axis, and 2) use the same graph layout for both plots.

import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
import csv

# load data
dictReader = csv.DictReader(open('nations.csv', 'rt'), fieldnames = ['entity1', 'relation', 'entity2'], delimiter = ',', quotechar = '"')

# create a more amenable data structure
edge_to_label = {(d['entity1'], d['entity2']) : d['relation'] for d in dictReader}

# create graph
G = nx.from_edgelist(edge_to_label.keys())

# precompute layout (default layout used here)
layout = nx.layout.fruchterman_reingold_layout(G)

# create figure so we plot the graph and labels on the same plot
fig, ax = plt.subplots(1,1)

# draw graph
nx.draw(G, pos=layout, ax=ax, with_labels=True)

# draw labels using the same, pre-computed graph layout
nx.draw_networkx_edge_labels(G, pos=layout, edge_labels=edge_to_label, ax=ax)

plt.show()

enter image description here

Upvotes: 2

Related Questions