基于networkx的异构图可视化方法

参考资料:基于networkx实现图可视化 - 知乎 (zhihu.com)

同构图可以直接调用networkx的函数实现可视化,网络上的教程有很多,但是networkx不能直接实现对异构图的可视化,基于上述参考资料,这里简要介绍一下如何利用networkx绘制异构图。

由于networkx中没有同构图与异构图的定义,为了绘制异构图,我们可将不同类型的节点归并在一起创建DiGraph,渲染时按类型分组,然后每组单独配置渲染参数即可。

本次实验选择的异构图如下

graph2 = dgl.heterograph(
    {('drug', 'interacts1', 'drug'): (torch.tensor([0, 1]), torch.tensor([1, 2])),
   ('drug', 'interacts2', 'gene'): (torch.tensor([0, 1]), torch.tensor([2, 3])),
   ('drug', 'treats', 'disease'): (torch.tensor([1]), torch.tensor([2]))})
print("medicine:",graph2)

输入的结果为:

medicine: Graph(num_nodes={'disease': 3, 'drug': 3, 'gene': 4},
      num_edges={('drug', 'interacts1', 'drug'): 2, ('drug', 'interacts2', 'gene'): 2, ('drug', 'treats', 'disease'): 1},
      metagraph=[('drug', 'drug', 'interacts1'), ('drug', 'gene', 'interacts2'), ('drug', 'disease', 'treats')])

可视化实现过程

"""
生成pos,用来配置layout,其格式为{0: [-0.95, -0.8],1: [-0.95, -0.48]}
"""


def gen_pos(node_type_num, node_num_array):
    step = round(1.6 / (node_type_num - 1), 2)
    xs = []
    for i in range(node_type_num):
        xs.append(round(-0.95 + i * step, 2))

    ys = []
    for node_num in node_num_array:
        cstep = round(1.6 / (node_num - 1), 2)
        result = []
        for j in range(node_num):
            result.append(round(-0.8 + j * cstep, 2))
        ys.append(result)

        # construct pos
    pos = []
    for aa, bb in zip(xs, ys):
        for b in bb:
            pos.append([aa, b])

    final_pos = {}
    for i, e in enumerate(pos):
        final_pos[i] = e
    return final_pos


pos = gen_pos(3, [3, 4, 3])

## 创建图对象,并添加节点,添加边
GG2 = nx.DiGraph()
# add nodes
GG2.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# add edges
res1=[(0, 1),(1,2)]
res2 = [(0,4),(2,6)]
res3 = [(1,9)]
GG2.add_edges_from(res1)
GG2.add_edges_from(res2)
GG2.add_edges_from(res3)

# nodes, 把节点分为三个组(相当于三种类型),每组独立编号与染色
plt.figure(figsize=(7, 5))
nx.draw_networkx_nodes(GG2, pos, nodelist=[0, 1, 2], node_color="red", label="drug")
nx.draw_networkx_nodes(GG2, pos, nodelist=[3,4,5,6], node_color="green", label="gene")
nx.draw_networkx_nodes(GG2, pos, nodelist=[7,8,9], node_color="blue", label="disease")

# edges,把边分为两个组(相当于两种边类型),每组独立设置样式
nx.draw_networkx_edges(GG2, pos, edgelist=res1, width=1,label="interacts1")
nx.draw_networkx_edges(GG2, pos, edgelist=res2, width=1,style="-.",label="interacts2")
nx.draw_networkx_edges(GG2, pos, edgelist=res3, width=1, style="dashed",label="treats")

# node labels,每类节点从0开始编号
labels = {0: "0", 1: "1", 2: "2", 3: "0", 4: "1", 5: "2",
          6: "3", 7: "0", 8: "1", 9: "2",}
nx.draw_networkx_labels(GG2, pos, labels, font_size=12, font_color="whitesmoke")

# legend1:渲染节点类型,labelspacing设置节点间距离(垂直方向)、borderpad设置节点与边界间距离(垂直方向)
l1 = plt.legend(bbox_to_anchor=(1, 0.85), labelspacing=1, borderpad=0.7)
plt.gca().add_artist(l1)  # 这条语句可使plt添加多个legend

# legend2:渲染边类型
from matplotlib.lines import Line2D

handles = [Line2D([], [], color="black", label="interacts1", linewidth=1),
           Line2D([], [], color="black", label="interacts2", linewidth=1, ls="-."),
           Line2D([], [], color="black", label="treats", linewidth=1, ls="dashed")]
plt.legend(handles=handles, bbox_to_anchor=(1, 0.6))

# dpi设置清晰度、bbox_inches='tight'保证图片能被完整保存
plt.savefig("e:\\hetero", dpi=1000, bbox_inches='tight')

最终生成的图为

基于networkx的异构图可视化方法_第1张图片

你可能感兴趣的:(python,网络,图论)