如何使用用户定义的 class 对象作为 networkx 节点?
How to use user-defined class object as a networkx node?
Class点定义为(里面也有一些方法,属性之类的东西,但这是最小的部分):
class point():
def ___init___(self, x, y):
self.x = x
self.y = y
所以,我看到了 this question,但是当我尝试应用它时,它 returns 出现错误:
G = nx.Graph()
p = point(0,0)
G.add_node(0, p)
NetworkXError: attr_dict 参数必须是字典。
如果我使用
G = nx.Graph()
p = point(0,0)
G.add_node(0, data = p)
我没有收到错误,但是当我尝试访问 x 坐标时,结果发现它没有将其保存为一个点。
G[0].x
returns: AttributeError: 'dict' 对象没有属性 'x'
正在做
G = nx.Graph()
G.add_node(0, data = point(0,0))
G[0]
returns:
{}
这意味着它仍将其保存为字典。
我看到我可以使我的点可散列,并将这些对象用作节点,所以我添加了属性 id,因为点会移动。我将其添加到 class 和 __repr__ 中以便更好地绘制图形:
def __hash__(self):
return self.id_n
def __cmp__(self, p):
if self.id_n < p.id_n: return -1
elif self.id_n == p.id_n: return 0
else: return 1
def __eq__(self, p):
if p.id_n == self.id_n: return True
else: return False
def __repr__(self):
return str(self.id_n)
但这有点奇怪,因为我不知道如何 select 一个节点,
G[<what should i put here?>]
所以,问题是,执行此操作的正确方法是什么?
我希望能够使用类似
的东西
G[node_id].some_method(some_args)
您已经添加了一个 node
,因此,您可以检查 nodes
,它是一个 set-like 视图。引用文档:
These are set-like views of the nodes, edges, neighbors (adjacencies), and degrees of nodes in a graph. They offer a continually updated read-only view into the graph structure.
举个例子:
mynodes = list(G.nodes())
print(mynodes)
您现在应该也可以:
mynode = mynodes[0] # because we have converted the set-like view to a list
查看教程:https://networkx.github.io/documentation/stable/tutorial.html
编辑 - 在下面,将 G.node[]
替换为 G.nodes[]
- 在版本 2.4 中 G.node
已被弃用。
您正在查看 G[0]
。但这不是你想要的。 G[0]
包含节点0
的邻居信息和边的属性,但不包含节点0
的属性。
class point():
def __init__(self, x, y):
self.x = x
self.y = y
import networkx as nx
G = nx.Graph()
p0 = point(0,0)
p1 = point(1,1)
G.add_node(0, data=p0)
G.add_node(1, data=p1)
G.add_edge(0,1, weight=4)
G[0]
> AtlasView({1: {'weight': 4}}) #in networkx 1.x this is actually a dict. In 2.x it is an "AtlasView"
对于 networkx,期望一个节点可能有大量与之关联的数据。在您的情况下,您只有一条数据,即点。但是您也可以指定颜色、重量、时间、年龄等。因此 networkx 将把所有属性存储在另一个字典中,但是该字典是通过 G.node[0]
而不是 G[0]
.
G.node[0]
> {'data': <__main__.point at 0x11056da20>}
G.node[0]['data'].x
> 0
请注意,您输入的 data
变为字符串 'data'
。
输入 G.add_node(0, x=0, y=0)
这样的节点可能会更好,然后您可以访问 G.node[0]['x']
.
的条目
我想我明白你的问题了。
您想使用已定义为节点的 class 实例,并能够轻松访问实例属性或方法。
当您在 networkx 中使用类似以下内容创建图形时:
G = nx.DiGraph() # create graph
G.add_nodes_from([node0, node1, node2]) # add 3 nodes
G.nodes[node0]["node_attribute0"] = "value0"
G.add_edges_from([(node0, node1), (node0, node2)]) # add 2 edges
G[node0][node1]["edge_attribute0"] = "value1" # add one attribute to edge
G[node0][node1]["edge_attribute1"] = 10 # add another attribute to same edge
networkx 创建嵌套的 python 字典,例如在有向图的情况下,3 个嵌套的字典如下:
'''
G = {
node0 : {
node1 : {
"edge_attribute0" : "value1",
"edge_attribute1" : 10
},
node2 : {}
},
node1 : {},
node2 : {}
}
'''
这就是为什么您使用连续的 [key]
访问每个
G[node0] # = output dict of dict, with neighbours on top layer
G[node0][node1] # = output dict with edge attributes
G[node0][node1][attribute0] # = output value
现在,节点属性不会存储在那些嵌套字典的任何位置。
它们位于一个单独的嵌套字典中,您可以通过 G.nodes:
访问
'''
G.nodes = {
node0 : {
"node_attribute0" : "value0"
}
}
'''
您可以像这样使用 G.nodes 来访问其他字典:
G.nodes[node0]["node_attribure0"] # = value assigned to key
如您所见,2 个字典嵌套中的任何一个都无法将节点作为对象本身来访问,因为在所有情况下它们都只是字典“键”。
解决方法是将节点对象本身存储为节点属性,为此您可以使用“self”作为方便的键:
for node in G: # iterate over all nodes in G
G.nodes[node]["self"] = node # create new node attribute = node
现在,如果 node0、node1、node2 是您之前定义的 class 的所有实例,假设有一个名为“variable”的变量和一个名为“method”的方法,您现在可以访问这些通过使用:
G.nodes[node0]["self"].variable
G.nodes[node0]["self"].method()
Class点定义为(里面也有一些方法,属性之类的东西,但这是最小的部分):
class point():
def ___init___(self, x, y):
self.x = x
self.y = y
所以,我看到了 this question,但是当我尝试应用它时,它 returns 出现错误:
G = nx.Graph()
p = point(0,0)
G.add_node(0, p)
NetworkXError: attr_dict 参数必须是字典。
如果我使用
G = nx.Graph()
p = point(0,0)
G.add_node(0, data = p)
我没有收到错误,但是当我尝试访问 x 坐标时,结果发现它没有将其保存为一个点。
G[0].x
returns: AttributeError: 'dict' 对象没有属性 'x'
正在做
G = nx.Graph()
G.add_node(0, data = point(0,0))
G[0]
returns: {}
这意味着它仍将其保存为字典。
我看到我可以使我的点可散列,并将这些对象用作节点,所以我添加了属性 id,因为点会移动。我将其添加到 class 和 __repr__ 中以便更好地绘制图形:
def __hash__(self):
return self.id_n
def __cmp__(self, p):
if self.id_n < p.id_n: return -1
elif self.id_n == p.id_n: return 0
else: return 1
def __eq__(self, p):
if p.id_n == self.id_n: return True
else: return False
def __repr__(self):
return str(self.id_n)
但这有点奇怪,因为我不知道如何 select 一个节点,
G[<what should i put here?>]
所以,问题是,执行此操作的正确方法是什么?
我希望能够使用类似
的东西G[node_id].some_method(some_args)
您已经添加了一个 node
,因此,您可以检查 nodes
,它是一个 set-like 视图。引用文档:
These are set-like views of the nodes, edges, neighbors (adjacencies), and degrees of nodes in a graph. They offer a continually updated read-only view into the graph structure.
举个例子:
mynodes = list(G.nodes())
print(mynodes)
您现在应该也可以:
mynode = mynodes[0] # because we have converted the set-like view to a list
查看教程:https://networkx.github.io/documentation/stable/tutorial.html
编辑 - 在下面,将 G.node[]
替换为 G.nodes[]
- 在版本 2.4 中 G.node
已被弃用。
您正在查看 G[0]
。但这不是你想要的。 G[0]
包含节点0
的邻居信息和边的属性,但不包含节点0
的属性。
class point():
def __init__(self, x, y):
self.x = x
self.y = y
import networkx as nx
G = nx.Graph()
p0 = point(0,0)
p1 = point(1,1)
G.add_node(0, data=p0)
G.add_node(1, data=p1)
G.add_edge(0,1, weight=4)
G[0]
> AtlasView({1: {'weight': 4}}) #in networkx 1.x this is actually a dict. In 2.x it is an "AtlasView"
对于 networkx,期望一个节点可能有大量与之关联的数据。在您的情况下,您只有一条数据,即点。但是您也可以指定颜色、重量、时间、年龄等。因此 networkx 将把所有属性存储在另一个字典中,但是该字典是通过 G.node[0]
而不是 G[0]
.
G.node[0]
> {'data': <__main__.point at 0x11056da20>}
G.node[0]['data'].x
> 0
请注意,您输入的 data
变为字符串 'data'
。
输入 G.add_node(0, x=0, y=0)
这样的节点可能会更好,然后您可以访问 G.node[0]['x']
.
我想我明白你的问题了。
您想使用已定义为节点的 class 实例,并能够轻松访问实例属性或方法。
当您在 networkx 中使用类似以下内容创建图形时:
G = nx.DiGraph() # create graph
G.add_nodes_from([node0, node1, node2]) # add 3 nodes
G.nodes[node0]["node_attribute0"] = "value0"
G.add_edges_from([(node0, node1), (node0, node2)]) # add 2 edges
G[node0][node1]["edge_attribute0"] = "value1" # add one attribute to edge
G[node0][node1]["edge_attribute1"] = 10 # add another attribute to same edge
networkx 创建嵌套的 python 字典,例如在有向图的情况下,3 个嵌套的字典如下:
'''
G = {
node0 : {
node1 : {
"edge_attribute0" : "value1",
"edge_attribute1" : 10
},
node2 : {}
},
node1 : {},
node2 : {}
}
'''
这就是为什么您使用连续的 [key]
访问每个G[node0] # = output dict of dict, with neighbours on top layer
G[node0][node1] # = output dict with edge attributes
G[node0][node1][attribute0] # = output value
现在,节点属性不会存储在那些嵌套字典的任何位置。 它们位于一个单独的嵌套字典中,您可以通过 G.nodes:
访问'''
G.nodes = {
node0 : {
"node_attribute0" : "value0"
}
}
'''
您可以像这样使用 G.nodes 来访问其他字典:
G.nodes[node0]["node_attribure0"] # = value assigned to key
如您所见,2 个字典嵌套中的任何一个都无法将节点作为对象本身来访问,因为在所有情况下它们都只是字典“键”。
解决方法是将节点对象本身存储为节点属性,为此您可以使用“self”作为方便的键:
for node in G: # iterate over all nodes in G
G.nodes[node]["self"] = node # create new node attribute = node
现在,如果 node0、node1、node2 是您之前定义的 class 的所有实例,假设有一个名为“variable”的变量和一个名为“method”的方法,您现在可以访问这些通过使用:
G.nodes[node0]["self"].variable
G.nodes[node0]["self"].method()