多层或组的 Networkx 绘图布局
Networkx drawing layout for multilayer or group
我要用python3和networkx
模块画一个网络。
首先,很抱歉我无法编写任何示例代码,因为我没有收到任何原始数据。
网络由3组节点组成,下图是我想象的。
是手绘的
我想参考任何布局或提示来绘制这种上面。
我知道Multipartite Layout
https://networkx.org/documentation/stable/auto_examples/drawing/plot_multipartite_graph.html#multipartite-layout,但是,我不确定它是否适合我。
谢谢。
多部分布局将根据您指定的分区将您的节点放在 rows/columns 中,但看起来您想要的是对齐您的节点,以便提供的 groups/partitions聚集在一起并与其他 groups/clusters 分开。您可以通过创建一个可以传递给 networkx
绘图函数的位置字典来实现。下面的示例函数采用您的图表,Graph 对象中节点属性的名称,指定每个节点属于哪个 group/partition (partition_attr
),一个可选的分区名称列表,指定您想要的顺序从左到右显示您的 groups/components (partition_order
) 以及不同分区中节点之间的最小值 space (epsilon
)。
#%% Function to make position dicts by partition
def make_node_positions(graph,partition_attr,partition_order=None,epsilon=.5):
if not partition_order:
# get a list of all the partition names if not specified
partition_order = list(set(dict(graph.nodes(data=partition_attr)).values()))
# make position dict for each partition
orig_partition_pos_dicts = {partition:nx.spring_layout(graph.subgraph([node for node,part in graph.nodes(data=partition_attr)
if part == partition]))
for partition in partition_order}
# update the x coordinate in the position dicts so partitions
# don't overlap and are in the specified order left-to-right
final_pos_dict = orig_partition_pos_dicts[partition_order[0]]
for i,partition in enumerate(partition_order[1:]):
# get the largest x coordinate from the previous partition's nodes
max_previous = max([x for x,y in final_pos_dict.values()])
# get smallest x coordinate from this partition's nodes
current_min = min([x for x,y in orig_partition_pos_dicts[partition].values()])
# update the x coordinates for this partition to be at least epsilon units
# to the right of the right-most node in the previous partition
final_pos_dict.update({node:(pos[0]+max_previous+abs(current_min)+epsilon,pos[1])
for node,pos in orig_partition_pos_dicts[partition].items()})
return(final_pos_dict)
现在我制作了一个与您的绘图相似的图表并应用了下面的函数
#%% Set up toy graph
import networkx as nx
# make the initial graphs
k5 = nx.complete_graph(5)
triangle=nx.from_edgelist([(5,6),(6,7),(5,7)])
single_node = nx.Graph()
single_node.add_node(8)
# edges to connect the components
extra_edges = [(3,5),(2,6),(5,8),(6,8),(7,8)]
# combine graphs and specify the original graphs
orig_graphs = {'k5':{'graph':k5,'color':'blue'},
'triangle':{'graph':triangle,'color':'green'},
'single_node':{'graph':single_node,'color':'red'}}
g = nx.Graph()
for g_name,g_val_dict in orig_graphs.items():
# add the nodes from that graph and specify the partition and node colors
g.add_nodes_from(g_val_dict['graph'].nodes,partition=g_name,color=g_val_dict['color'])
if len(g_val_dict['graph'].edges) > 0:
# if the graph has edges then add the edges
g.add_edges_from(g_val_dict['graph'].edges,partition=g_name,color=g_val_dict['color'])
# add the extra edges to combine the graphs
g.add_edges_from(extra_edges,color='black')
#%% Draw graph #####
my_pos = make_node_positions(g,partition_attr='partition',partition_order=['k5','triangle','single_node'])
nx.draw_networkx_nodes(g,my_pos,node_color=[c for n,c in g.nodes(data='color')])
nx.draw_networkx_labels(g,my_pos)
nx.draw_networkx_edges(g,my_pos,edge_color=[c for u,v,c in g.edges(data='color')])
我要用python3和networkx
模块画一个网络。
首先,很抱歉我无法编写任何示例代码,因为我没有收到任何原始数据。
网络由3组节点组成,下图是我想象的。
是手绘的
我想参考任何布局或提示来绘制这种上面。
我知道Multipartite Layout
https://networkx.org/documentation/stable/auto_examples/drawing/plot_multipartite_graph.html#multipartite-layout,但是,我不确定它是否适合我。
谢谢。
多部分布局将根据您指定的分区将您的节点放在 rows/columns 中,但看起来您想要的是对齐您的节点,以便提供的 groups/partitions聚集在一起并与其他 groups/clusters 分开。您可以通过创建一个可以传递给 networkx
绘图函数的位置字典来实现。下面的示例函数采用您的图表,Graph 对象中节点属性的名称,指定每个节点属于哪个 group/partition (partition_attr
),一个可选的分区名称列表,指定您想要的顺序从左到右显示您的 groups/components (partition_order
) 以及不同分区中节点之间的最小值 space (epsilon
)。
#%% Function to make position dicts by partition
def make_node_positions(graph,partition_attr,partition_order=None,epsilon=.5):
if not partition_order:
# get a list of all the partition names if not specified
partition_order = list(set(dict(graph.nodes(data=partition_attr)).values()))
# make position dict for each partition
orig_partition_pos_dicts = {partition:nx.spring_layout(graph.subgraph([node for node,part in graph.nodes(data=partition_attr)
if part == partition]))
for partition in partition_order}
# update the x coordinate in the position dicts so partitions
# don't overlap and are in the specified order left-to-right
final_pos_dict = orig_partition_pos_dicts[partition_order[0]]
for i,partition in enumerate(partition_order[1:]):
# get the largest x coordinate from the previous partition's nodes
max_previous = max([x for x,y in final_pos_dict.values()])
# get smallest x coordinate from this partition's nodes
current_min = min([x for x,y in orig_partition_pos_dicts[partition].values()])
# update the x coordinates for this partition to be at least epsilon units
# to the right of the right-most node in the previous partition
final_pos_dict.update({node:(pos[0]+max_previous+abs(current_min)+epsilon,pos[1])
for node,pos in orig_partition_pos_dicts[partition].items()})
return(final_pos_dict)
现在我制作了一个与您的绘图相似的图表并应用了下面的函数
#%% Set up toy graph
import networkx as nx
# make the initial graphs
k5 = nx.complete_graph(5)
triangle=nx.from_edgelist([(5,6),(6,7),(5,7)])
single_node = nx.Graph()
single_node.add_node(8)
# edges to connect the components
extra_edges = [(3,5),(2,6),(5,8),(6,8),(7,8)]
# combine graphs and specify the original graphs
orig_graphs = {'k5':{'graph':k5,'color':'blue'},
'triangle':{'graph':triangle,'color':'green'},
'single_node':{'graph':single_node,'color':'red'}}
g = nx.Graph()
for g_name,g_val_dict in orig_graphs.items():
# add the nodes from that graph and specify the partition and node colors
g.add_nodes_from(g_val_dict['graph'].nodes,partition=g_name,color=g_val_dict['color'])
if len(g_val_dict['graph'].edges) > 0:
# if the graph has edges then add the edges
g.add_edges_from(g_val_dict['graph'].edges,partition=g_name,color=g_val_dict['color'])
# add the extra edges to combine the graphs
g.add_edges_from(extra_edges,color='black')
#%% Draw graph #####
my_pos = make_node_positions(g,partition_attr='partition',partition_order=['k5','triangle','single_node'])
nx.draw_networkx_nodes(g,my_pos,node_color=[c for n,c in g.nodes(data='color')])
nx.draw_networkx_labels(g,my_pos)
nx.draw_networkx_edges(g,my_pos,edge_color=[c for u,v,c in g.edges(data='color')])