1

I want to draw a bipartite graph connecting colleagues and moviepreferences. How can I show in the graph both the node name (so the moviename or colleague name) and the node attribute (whether it is a colleague or a movie) in the nodes ?

My current code only displays the node attribute and drops the node name.

My code:

BG = nx.Graph()
BG.add_nodes_from(employees, bipartite=0, _type='employee')
BG.add_nodes_from(movies, bipartite=1, _type='movie')
edgeinfo = pd.read_csv('Employee_Movie_Choices.txt', sep='\t')
edges = [tuple(x) for x in edgeinfo.values]
BG.add_edges_from(edges)

labels = dict((n,d['_type']) for n,d in BG.nodes(data=True))

%matplotlib notebook
import matplotlib.pyplot as plt

plt.figure()
pos = nx.spring_layout(BG)
edges = BG.edges()
nx.draw_networkx(BG, pos, edges=edges, labels=labels)

If I create label tuples, he gives me an error:

BG = nx.Graph()
BG.add_nodes_from(employees, bipartite=0, _type='employee')
BG.add_nodes_from(movies, bipartite=1, _type='movie')
edgeinfo = pd.read_csv('Employee_Movie_Choices.txt', sep='\t')
edges = [tuple(x) for x in edgeinfo.values]
BG.add_edges_from(edges)

labels = dict((n,d['_type']) for n,d in BG.nodes(data=True))  ###ik krijg hier naam movie en employee niet meer bij !!!
labels_new = [(k, v) for k, v in labels.items()]
#labels = [tuple(n,d['_type']) for n, d in BG.nodes(data=True)]
#nx.draw(BG, labels=labels)

%matplotlib notebook
import matplotlib.pyplot as plt

plt.figure()
pos = nx.spring_layout(BG)
edges = BG.edges()
nx.draw_networkx(BG, pos, edges=edges, labels=labels_new)

Error: ---> nx.draw_networkx(BG, pos, edges=edges, labels=labels_new) AttributeError: 'list' object has no attribute 'items'

Tai
  • 7,684
  • 3
  • 29
  • 49
Wendy De Wit
  • 293
  • 2
  • 3
  • 6

1 Answers1

1

Why error arises

From the documentation of draw_networkx , labels needs to be a dictionary while labels_new you fed is a list.

labels (dictionary, optional (default=None)) – Node labels in a dictionary keyed by node of text labels

From your code,

labels_new=[(k, v) for k, v in labels.items()]

Thus, the error AttributeError: 'list' object has no attribute 'items' arises.

Workaround: customize the labels dictionary

I do not have the data, but a quick hack can be

labels = dict((n, "(" + n + "," + d['_type'] + ")") for n,d in BG.nodes(data=True))

Demo

import networkx as nx
from networkx.algorithms import bipartite
%matplotlib notebook
import matplotlib.pyplot as plt

BG = nx.Graph()
employees = [str(i) for i in range(3)]
movies = ["mA", "mB", "mC"]
BG.add_nodes_from(employees, bipartite=0, _type='emp')
BG.add_nodes_from(movies, bipartite=1, _type='mov')
edges = [("0", "mA"), ("0", "mC"), ("1", "mA"),("1", "mB"), ("2", "mA")]
BG.add_edges_from(edges)
labels = dict((n, "(" + n + "," + d['_type'] + ")") for n,d in BG.nodes(data=True))

# Setting up pos for drawing bipartite graph. See the reference for more info
X, Y = bipartite.sets(BG)
pos = dict()
pos.update( (n, (1, i)) for i, n in enumerate(X) ) # put nodes from X at x=1
pos.update( (n, (2, i)) for i, n in enumerate(Y) ) # put nodes from Y at x=2

plt.figure()
edges = BG.edges()
nx.draw_networkx(BG, pos, edges=edges, labels=labels)

enter image description here

Reference

mdml's answer for drawing bipartite graph

Tai
  • 7,684
  • 3
  • 29
  • 49