networkx:以分层方式绘制

问题描述

我想画一个分层的图 如果您可以看下面的图,可以按以下方式订购它

 95   85
 21  31
 42  52  62  22 32
 13
 14

如果需要,我可以提供提示,提示哪个节点位于哪一层。

过去,我也有类似的需求,但是在这种情况下不起作用: NetworkX: draw graph in layers

我尝试了所有标准布局和所有graph_viz布局:“。dot”,“ twopi”,“ fdp”,“ sfdp”,“ circo”

enter image description here


“分层”是指每组节点都在同一层上(垂直坐标:Y)

就像我已经在上面订购了它们...


这是我的第一个裂缝...现在我必须根据边缘更清楚地进行x轴处理。谢谢mathfux

def layered_layout(nodes,base):
    nodes = np.array(nodes)

    ncols = np.unique( nodes % base,return_counts=True)[1].max()                                                                                                                      
    nlayers = np.unique(nodes % base).size
    ys = np.linspace(0,1,nlayers)
    xs = np.linspace(0,ncols)
    pos = {}
    for j,b in enumerate(np.unique(nodes % base)):
        ixs = np.where(nodes % base == b)[0]
    
        for i,x in enumerate(ixs) :
            node = nodes[x]
            pos[node] = (xs[i],ys[j])

    return pos      

解决方法

如果找不到任何默认布局,则可以定义自定义布局。分层方式似乎并不复杂。

def layered_layout(layers,stretch=0,alignment='c'):
    sizes = np.array([len(n) for n in layers])
    lfill = [np.linspace(0,1,n) for n in sizes]
    scales = (sizes - 1)/(max(sizes) - 1)
    if alignment == 'l':
        x_coord_levels = [(x - x[0]) * (s + (1 - s) * stretch) for x,s in zip(lfill,scales)]
    elif alignment == 'r':
        x_coord_levels = [(x - x[-1]) * (s + (1 - s) * stretch) for x,scales)]
    elif alignment == 'c':
        x_coord_levels = [(x - (x[0]+x[-1])/2) * (s + (1 - s) * stretch) for x,scales)]
    else:
        raise AttributeError('invalid alignment attribute')
    y_coord_levels = [np.repeat(-y,times) for y,times in zip(np.arange(len(sizes)),sizes)]
    pos_levels = [dict(zip(l,zip(*p))) for l,p in zip(layers,zip(x_coord_levels,y_coord_levels))]
    pos = {k: v for d in pos_levels for k,v in d.items()}
    return pos

创建图形后:

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
G = nx.DiGraph()
G.add_edges_from([(21,42),(52,13),(42,(95,21),(31,52),62),31),(62,(32,95),(13,22),(85,(22,14),(14,32)])
nx.set_edge_attributes(G,{(21,42): 0.20,13): 0.52,13): 0.49,21): 0.15,52): 0.52,62): 0.42,31): 0.47,13): 0.42,95): 0.42,22): 0.71,31): -0.00,14): 0.74,32): 0.74},'w')

layered_layout应该用于定义pos参数的值:

layers = [[95,85],[21,31,42],[52,62,22,32],[13],[14]]
pos = layered_layout(layers,stretch=...,alignment=...)

用法示例:

layers = [[95,[14]]
fig = plt.figure(figsize=(20,10))
for i in range(3):
    for j in range(3):
        ax = fig.add_subplot(3,3,1+3*j+i)
        ax.set_title(f'stretch = {[0,0.5,1][j]},alignment={"lcr"[i]}')
        pos = layered_layout(layers,stretch = [0,1][j],alignment='lcr'[i])
        nx.draw_networkx(G,pos,with_labels=True,font_size=7,node_size=100)
        nx.draw_networkx_edge_labels(G,edge_labels = nx.get_edge_attributes(G,'w'),font_size=7)
        plt.axis('on'); plt.tick_params(left=True,bottom=True,labelleft=True,labelbottom=True)
plt.show()

enter image description here

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...