全部,
考虑下面的样本“树状”图。
垂直地,它是基于节点“0”的级别层次结构。 水平地,它是从级别1开始的基于组的结构,组是指从一个根节点继承的节点
'''
+---+
| 0 | Level 0
+---+
|
+--------------+---------------+
| | |
+---+ +---+ +---+
| 1 | | 2 | | 3 | Level 1
+---+ +---+ +---+
+-----+----+ +-----+-----+ +|---+-----+
| | | | | | | | |
+---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+
|11 | |12 | |13 | |21 | |22 | |23 | |31 | |32 | |33 | Level 2
+---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+
| | / | / | | |
| | / | / | | |
| +---+ +---+ +---+ +---+ |
| |121|-|131| |211| |221| | Level 3
| +---+ +---+ +---+ +---+ |
| |--------|------| |
|-----------|----------------------------|
| Group 0 | group 1 | group 2 |
'''
在Networkx中创建:
# create it in networkx
import networkx as nx
G = nx.DiGraph()
G.add_edges_from([('0', '1'), ('0', '2'), ('0', '3')])
G.add_edges_from([('1', '11'), ('1', '12'), ('1', '13')])
G.add_edges_from([('2', '21'), ('2', '22'), ('2', '23')])
G.add_edges_from([('3', '31'), ('3', '32'), ('3', '33')])
#
G.add_edges_from([('12', '121'), ('13', '131')])
G.add_edges_from([('12', '121'), ('13', '131')])
G.add_edges_from([('21', '211'), ('22', '221')])
#
G.add_edges_from([('13', '121')])
G.add_edges_from([('21', '131')])
G.add_edges_from([('131', '211')])
G.add_edges_from([('131', '221')])
#
G.add_edges_from([('121', '13')]) # node may not with "in_degree" link only
G.add_edges_from([('131', '21')]) # ditto
#
G.add_edges_from([('131', '31')])
G.add_edges_from([('131', '11')])
G.add_edges_from([('11', '131')])
#
G.add_edges_from([('121', '131')])
问题:
如何使用以下节点作为示例在Graph中找出节点和边:
“121”,在同一组中有多个指向更高级别的链接? (节点边缘类型“不确定”,可以in_degree或out_degree或两者,在以下问题中相同)
“131”,有多个指向较高级别节点的链接到其他组?
“131”,包含指向同一组中相同级别节点的链接
“131”,包含指向相同级别节点但在其他组中的链接
“21”,包含指向不同组中较低级别节点的链接
“Graph”的新手,并尝试获取示例代码,了解如何更深入地使用networkx。
非常感谢。
答案 0 :(得分:2)
首先,您应该以某种方式定义节点在哪个组或级别,因为它未在图形istelf中定义,因为其他边缘会破坏树结构。 我只是按照你的命名模式编写了这些辅助函数,将给定的名称转换为级别/组:
def get_group(node):
if node == '0':
return 1
return int(node[0])-1
def get_level(node):
if node == '0':
return 0
return len(node)
def equal_group(a,b):
return get_group(a) == get_group(b)
def lower_level(a,b):
return get_level(a) < get_level(b)
def equal_level(a,b):
return get_level(a) == get_level(b)
然后您可以根据您的规范过滤节点:
def filter_q1(node):
k = len([predecessor for predecessor in G.predecessors_iter(node) if equal_group(node, predecessor) and lower_level(predecessor, node)] )
return k > 1
q1_result = filter(filter_q1, G)
print 'Q1:', q1_result
def filter_q2(node):
k = len([predecessor for predecessor in G.predecessors_iter(node) if lower_level(predecessor, node)])
return k > 1
q2_result = filter(filter_q2, G)
print 'Q2:', q2_result
def filter_q3(node):
k = len([neighbour for neighbour in G.neighbors_iter(node) if equal_level(node, neighbour) and equal_group(node, neighbour)])
return k > 0
q3_result = filter(filter_q3, G)
print 'Q3:', q3_result
def filter_q4(node):
k = len([neighbour for neighbour in G.neighbors_iter(node) if equal_level(node, neighbour)])
return k > 0
q4_result = filter(filter_q4, G)
print 'Q4:', q4_result
def filter_q5(node):
k = len([neighbour for neighbour in G.neighbors_iter(node) if not equal_group(node, neighbour)])
return k > 0
q5_result = filter(filter_q5, G)
print 'Q5:', q5_result
结果看起来像这样:
>>>Q1: ['131', '121']
>>>Q2: ['131', '121']
>>>Q3: ['121']
>>>Q4: ['131', '121']
>>>Q5: ['21', '131', '0']
一般情况下,您可以找到不需要的边缘:
def is_bad_edge(edge):
a, b = edge
if not equal_group(a, b):
return True
if not lower_level(a, b):
return True
return False
bad_edges = filter(is_bad_edge, G.edges_iter())
print 'Bad edges:', bad_edges
结果如下:
>>>Bad edges: [('21', '131'), ('131', '11'), ('131', '31'), ('131', '21'), ('131', '221'), ('131', '211'), ('121', '13'), ('121', '131'), ('0', '1'), ('0', '3')]
正如您所看到的那样,您的0
边缘也在那里,因为它被归类为第1组,但节点1
和节点3
不是。根据您对节点0
的分类方式,您可以调整函数以包含或排除根节点。
答案 1 :(得分:2)
这样的事可能有用。它使用节点的长度作为级别(必须在代码中注释掉您的级别0节点以使其工作)并将节点字符串的第一个元素作为组。我认为这就是您对数据结构的意图。
# create it in networkx
import networkx as nx
G = nx.DiGraph()
#G.add_edges_from([('0', '1'), ('0', '2'), ('0', '3')])
G.add_edges_from([('1', '11'), ('1', '12'), ('1', '13')])
G.add_edges_from([('2', '21'), ('2', '22'), ('2', '23')])
G.add_edges_from([('3', '31'), ('3', '32'), ('3', '33')])
#
G.add_edges_from([('12', '121'), ('13', '131')])
G.add_edges_from([('12', '121'), ('13', '131')])
G.add_edges_from([('21', '211'), ('22', '221')])
#
G.add_edges_from([('13', '121')])
G.add_edges_from([('21', '131')])
G.add_edges_from([('131', '211')])
G.add_edges_from([('131', '221')])
#
G.add_edges_from([('121', '13')]) # node may not with "in_degree" link only
G.add_edges_from([('131', '21')]) # ditto
#
G.add_edges_from([('131', '31')])
G.add_edges_from([('131', '11')])
G.add_edges_from([('11', '131')])
G.add_edges_from([('121', '131')])
# "121", with more than one link to higher level in same group? (node edge type "unsure", may in_degree or out_degree or both, same in following question)
print "more than one link to higher level in same group"
for node in G:
l = len(node)-1 # higher level
others = [n for n in G.successors(node)+G.predecessors(node)
if len(n)==l and n[0]==node[0]]
if len(others) > 1:
print node
# "131", with more than one link to higner level nodes to other group?
print "more than one link to higher level in same group"
for node in G:
l = len(node)-1 # higher level
others = [n for n in G.successors(node)+G.predecessors(node)
if len(n)==l and n[0]!=node[0]]
if len(others) > 1:
print node
# "131", with links to same level nodes in same group
print "same level, same group"
for u,v in G.edges():
if len(u) == len(v):
if u[0] == v[0]:
print u
# "131", with links to same level nodes but in other group
print "same level, other group"
for u,v in G.edges():
if len(u) == len(v):
if u[0] != v[0]:
print u
# "21", with links to lower level nodes in different group
print "same level, other group"
for u,v in G.edges():
if len(u) == len(v)-1:
if u[0] != v[0]:
print u