NetworkX - 允许重复的节点标签吗?

3
我希望能够让很多节点拥有相同的标签——在我这个特殊情况下,每个节点代表一篇新闻文章,它们应该被标记为它们的新闻类别。最终,我真正想要的是一个带有这些标签的GML文件。
以下是一个小样例:
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"
  ]
]
"""

最终,我试图得到GML文件:
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"
  ]
]

是否可以为多个节点使用相同的标签/生成此输出文件?


你有什么问题? - DYZ
是否可以为多个节点使用相同的标签/生成相同的输出文件? - Dylan Baker
为什么不试试呢?(提示:是的,这是可能的。) - DYZ
1
我已经尝试了很长时间!我觉得肯定有什么明显的地方我忽略了,也许我对networkx的工作原理有一些理解上的空白?我对relabel_nodes为什么会合并具有相同标签的节点感到困惑。 - Dylan Baker
2个回答

5
这是一个示例,展示如何完成此操作:
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"))

图形[
节点[
id 0
label 1
]
节点[
id 1
label 2
]
]

NB 答案适用于networkx-1.1。 它在2.0或更高版本中无法使用。 相反,您可以设置节点属性:

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

问题是,对我来说至少是这样,当你想要对现有的图进行此操作时。(例如,我想使用一个图生成器_然后_重新标记节点。relabel_nodes()似乎使用新标签作为第一个参数添加节点。 - RhodriM
1
@RhodriM 答案是针对 networkx-1.1 给出的。它在2.0及以上版本中不起作用,因为这些版本不兼容。请查看更新后的答案。 - DYZ
谢谢DYZ,看起来很不错。我将在networkx的github论坛上询问关于relabel_nodes或您原始示例是否应该在较新版本中执行此操作。 - RhodriM
实际上不行,看起来你是在将标签添加到节点数据中,而不是更新标签本身,写入gml时会像往常一样得到相同的标签作为ID。 - RhodriM

0

您可以通过将自定义函数作为 write_gml 函数的 stringizer 参数来实现此操作。

以下是生成所需 GML 文件的代码:

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)

请注意,如果您在add_node中添加到图形的对象是int、float或dict,则不会调用stringizer函数。因此,上面的代码使用了自定义节点类。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接