python 利用matplotlib和graphviz在networkx中绘制多重图

jgzswidk  于 2023-01-04  发布在  Python
关注(0)|答案(4)|浏览(225)

当我将多图numpy邻接矩阵传递给networkx(使用from_numpy_matrix函数),然后尝试使用matplotlib绘制图时,它忽略了多条边。
我怎样才能让它同时画出多条边呢?

pw9qyyiw

pw9qyyiw1#

Graphviz在绘制平行边方面做得很好。你可以在NetworkX上使用它,写一个点文件,然后用Graphviz处理(例如下面的整洁布局)。除了NetworkX,你还需要pydot或pygraphviz

In [1]: import networkx as nx

In [2]: G=nx.MultiGraph()

In [3]: G.add_edge(1,2)

In [4]: G.add_edge(1,2)

In [5]: nx.write_dot(G,'multi.dot')

In [6]: !neato -T png multi.dot > multi.png

在NetworkX 1.11和更高版本中,nx.write_dot无法按照issue on networkx github工作。解决方法是使用以下命令调用write_dot
from networkx.drawing.nx_pydot import write_dot

from networkx.drawing.nx_agraph import write_dot

aydmsdu9

aydmsdu92#

您可以使用计算的节点位置直接使用matplotlib。

G=nx.MultiGraph ([(1,2),(1,2),(1,2),(3,1),(3,2)])
pos = nx.random_layout(G)
nx.draw_networkx_nodes(G, pos, node_color = 'r', node_size = 100, alpha = 1)
ax = plt.gca()
for e in G.edges:
    ax.annotate("",
                xy=pos[e[0]], xycoords='data',
                xytext=pos[e[1]], textcoords='data',
                arrowprops=dict(arrowstyle="->", color="0.5",
                                shrinkA=5, shrinkB=5,
                                patchA=None, patchB=None,
                                connectionstyle="arc3,rad=rrr".replace('rrr',str(0.3*e[2])
                                ),
                                ),
                )
plt.axis('off')
plt.show()

7bsow1i6

7bsow1i63#

您可以使用pyvis包。
我只是从我的Jupyter笔记本实际项目复制粘贴此代码。

from pyvis import network as pvnet

def plot_g_pyviz(G, name='out.html', height='300px', width='500px'):
    g = G.copy() # some attributes added to nodes
    net = pvnet.Network(notebook=True, directed=True, height=height, width=width)
    opts = '''
        var options = {
          "physics": {
            "forceAtlas2Based": {
              "gravitationalConstant": -100,
              "centralGravity": 0.11,
              "springLength": 100,
              "springConstant": 0.09,
              "avoidOverlap": 1
            },
            "minVelocity": 0.75,
            "solver": "forceAtlas2Based",
            "timestep": 0.22
          }
        }
    '''

    net.set_options(opts)
    # uncomment this to play with layout
    # net.show_buttons(filter_=['physics'])
    net.from_nx(g)
    return net.show(name)

G = nx.MultiDiGraph()
[G.add_node(n) for n in range(5)]
G.add_edge(0, 1, label=1)
G.add_edge(0, 1, label=11)
G.add_edge(0, 2, label=2)
G.add_edge(0, 3, label=3)
G.add_edge(3, 4, label=34)

plot_g_pyviz(G)

result

zd287kbt

zd287kbt4#

参考atomh33ls的答案

import numpy as np
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
import random as rd

column_from = 'from_here'
column_to = 'to_there'
column_attribute = 'edges_count'

# test data
pdf = pd.DataFrame([
                   ['a', 'b', 3], 
                   ['b', 'a', 1], 
                   ['a', 'c', 1], 
                   ['b', 'c', 1],
                   ['a', 'd', 1],
                   ['e', 'b', 2],
                   ['c', 'f', 1],
                   ['f', 'g', 1]],
                  columns=[column_from, column_to, column_attribute])
with pd.option_context('display.max_rows', None, 'display.max_columns', None):  # more options can be specified also
    print(pdf)

def get_adjacency_matrix(pdf):
    id_set = set(pdf[column_from].drop_duplicates().values.tolist() + 
                 pdf[column_to].drop_duplicates().values.tolist())
    id_dict_kv = {k : v for k, v in enumerate(id_set)}
    id_dict_vk = {v : k for k, v in id_dict_kv.items()}
    count = len(id_set)

    adjacency_matrix = np.zeros([count, count], dtype='int32')

    for row in pdf.itertuples():
        index_from = id_dict_vk[getattr(row, column_from)]
        index_to = id_dict_vk[getattr(row, column_to)]
        adjacency_matrix[index_from, index_to] += getattr(row, column_attribute)
    label_mapping = id_dict_kv
    return adjacency_matrix, label_mapping

def pdf_to_MDG(pdf):
    adjacency_matrix, label_mapping = get_adjacency_matrix(pdf)
    G = nx.from_numpy_matrix(adjacency_matrix, parallel_edges=True, create_using=nx.MultiDiGraph())
    G = nx.relabel_nodes(G, label_mapping)
    return G

MDG = pdf_to_MDG(pdf)

edges_data = MDG.edges.data(column_weight)
print(edges_data)

#—————————————————————————————just see the below: draw MultiDiGraph—————————————————————————————————

pos = nx.spring_layout(MDG, seed = 1)
nx.draw(MDG, pos, with_labels=True, edge_color = (1,1,1))
for e in MDG.edges:
    plt.gca().annotate("",
                       xy=pos[e[1]], 
                       xycoords='data',
                       xytext=pos[e[0]], 
                       textcoords='data',
                       arrowprops=dict(arrowstyle="->", color="0",
                                       shrinkA=15, shrinkB=15,
                                       patchA=None, patchB=None,
                                       connectionstyle="arc3,rad=rrr".replace('rrr',str(rd.random()*0.5+0.1)))
                      )
plt.axis('off')
plt.show()

输出:

from_here to_there  edges_count
0         a        b            3
1         b        a            1
2         a        c            1
3         b        c            1
4         a        d            1
5         e        b            2
6         c        f            1
7         f        g            1
[('c', 'f', 1), ('e', 'b', 1), ('e', 'b', 1), ('b', 'c', 1), ('b', 'a', 1), ('f', 'g', 1), ('a', 'c', 1), ('a', 'd', 1), ('a', 'b', 1), ('a', 'b', 1), ('a', 'b', 1)]

the output img

相关问题