Networkx - allow duplicate node labels?

2.6k Views Asked by At

I want to be able to have a lot of nodes have the same label— in my particular case, each node represents a news article, and they should be labelled with their news category. Ultimately, what I really want is a GML file with these labels.

Here's a small sample:

Gtest = nx.Graph()
nodes = [0, 1, 2, 3, 4]
labels = {0:"business", 1:"business",2:"sports", 3:"sports", 4:"politics"}

for node in nodes:
    Gtest.add_node(node)

print Gtest.nodes(data=True) 

""" 
this prints:
[(0, {}), (1, {}), (2, {}), (3, {}), (4, {})]

Which is good, I want 5 nodes.
"""

Gtest = nx.relabel_nodes(Gtest, labels)

print Gtest.nodes(data=True)

"""this prints:

[('business', {}), ('politics', {}), ('sports', {})]

There are only 3 nodes.
"""

nx.write_gml(Gtest, "gml/stackoverflow_test", stringizer = None)

"""
This writes the GML file:

graph [
  name "()"
  node [
    id 0
    label "business"
  ]
  node [
    id 1
    label "politics"
  ]
  node [
    id 2
    label "sports"
  ]
]
"""

Ultimately, I'm trying to end up with the GML file:

graph [
  name "()"
  node [
    id 0
    label "business"
  ]
  node [
    id 1
    label "business"
  ]
  node [
    id 2
    label "sports"
  ]
  node [
    id 3
    label "sports"
  ]
  node [
    id 4
    label "politics"
  ]
]

Is it possible to have the same label for multiple nodes/to generate this output file?

2

There are 2 best solutions below

4
DYZ On

Here's an example of how this can be done:

G = nx.Graph()
G.add_node(1, {'label' : 'foo'})
G.add_node(2, {'label' : 'foo'})
G.nodes(data=True)
#[(1, {'label': 'foo'}), (2, {'label': 'foo'})]
nx.write_gml(G,open("foo.gml","wb"))

graph [
node [
id 0
label 1
]
node [
id 1
label 2
]
]

NB The answer is for networkx-1.1. It does not work in 2.0 or above. Instead, you can set node attrribute:

nx.set_node_attributes(G, {1: 'foo', 2: 'foo'}, 'label')
G.nodes(data=True)
#NodeDataView({1: {'label': 'foo'}, 2: {'label': 'foo'}})
0
astraujums On

You can do this by passing a custom function as the stringizer argument to the write_gml function.

Here is a code that produces a GML file that you want:

import networkx as nx

class Article:
    def __init__(self, id, category):
        self.id = id
        self.category = category

    def get_category(self):
        return self.category

Gtest = nx.Graph()
nodes = [0, 1, 2, 3, 4]
labels = {0: "business", 1: "business", 2: "sports", 3: "sports", 4: "politics"}

for node in nodes:
    Gtest.add_node(Article(node, labels[node]))

nx.write_gml(Gtest, "articles.gml", stringizer=Article.get_category)

Please note that if the object that you add to the graph in add_node is an int, float, or dict, then the stringizer function will NOT be called. Therefore, the code above uses a custom class for nodes.