利用python(networkx库)画带权&不带权有向图、无向图

  当我们处理完几百几千乃至上万的图论数据后总是不可避免地要对数据进行数据可视化等的分析
  ,甚至要在画好图的基础上进行一些上层修改,增加连线,高亮特殊点和路径。比如说在Dijks-
  tra和  Floyd算法的时候,为了体现出它们的区别(Dijkstra是以起始点为中心向外扩散层层
  遍历得到迷宫式推  进最短路径,而 Floyd是考虑i,j之间分为的过点和不过点分类求最小的
  区别);或者生成最小二叉树的kruscal和prim算法,分别得出最小网络问题。都需要我们对网
  络节点进行归类和数据可视化。

在这里插入图片描述
具体算法介绍可以移步:传送门

效果展示

老规矩先上效果:
在我的数据中有80个节点,我希望挑出其中路径上比较重要的节点,断了之后回会对车流量的畅通造成极大的影响,于是我希望将重要节点表示出来并且将它联通的大村庄进行编号分组在这里插入图片描述
编号之后的效果如下:
在这里插入图片描述
下列绿色为重要的交通枢纽,黄色为普通节点,其他同颜色的表示是一个地点群的村庄。
考虑下一个因素,道路被破坏的情况,我利用算法算出在一定置信概率的情况下能继续保持能互相通行的解决办法,将交通网络进行增补形成环状交通枢纽的方案,之后的效果如下:在这里插入图片描述
标为蓝色的路线即为新增的村庄间道路。
做完这些已头秃。。在这里插入图片描述
这个是利用无向图函数可以达到的目的。

分段代码

无向图代码如下:
很多同学说Graph_Matrix没有给出,其实这个在大佬的原博客里是给出的,是一个类名,后来的可以借鉴一下!!


class Graph_Matrix:
    """
    Adjacency Matrix
    """
    def __init__(self, vertices=[], matrix=[]):
        """

        :param vertices:a dict with vertex id and index of matrix , such as {vertex:index}
        :param matrix: a matrix
        """
        self.matrix = matrix
        self.edges_dict = {}  # {(tail, head):weight}
        self.edges_array = []  # (tail, head, weight)
        self.vertices = vertices
        self.num_edges = 0

        # if provide adjacency matrix then create the edges list
        if len(matrix) > 0:
            if len(vertices) != len(matrix):
                raise IndexError
            self.edges = self.getAllEdges()
            self.num_edges = len(self.edges)

        # if do not provide a adjacency matrix, but provide the vertices list, build a matrix with 0
        elif len(vertices) > 0:
            self.matrix = [[0 for col in range(len(vertices))] for row in range(len(vertices))]

        self.num_vertices = len(self.matrix)

    def isOutRange(self, x):
        try:
            if x >= self.num_vertices or x <= 0:
                raise IndexError
        except IndexError:
            print("节点下标出界")

    def isEmpty(self):
        if self.num_vertices == 0:
            self.num_vertices = len(self.matrix)
        return self.num_vertices == 0

    def add_vertex(self, key):
        if key not in self.vertices:
            self.vertices[key] = len(self.vertices) + 1

        # add a vertex mean add a row and a column
        # add a column for every row
        for i in range(self.getVerticesNumbers()):
            self.matrix[i].append(0)

        self.num_vertices += 1

        nRow = [0] * self.num_vertices
        self.matrix.append(nRow)

    def getVertex(self, key):
        pass

    def add_edges_from_list(self, edges_list):  # edges_list : [(tail, head, weight),()]
        for i in range(len(edges_list)):
            self.add_edge(edges_list[i][0], edges_list[i][1], edges_list[i][2], )

    def add_edge(self, tail, head, cost=0):
        # if self.vertices.index(tail) >= 0:
        #   self.addVertex(tail)
        if tail not in self.vertices:
            self.add_vertex(tail)
        # if self.vertices.index(head) >= 0:
        #   self.addVertex(head)
        if head not in self.vertices:
            self.add_vertex(head)

        # for directory matrix
        self.matrix[self.vertices.index(tail)][self.vertices.index(head)] = cost
        # for non-directory matrix
        # self.matrix[self.vertices.index(fromV)][self.vertices.index(toV)] = \
        #   self.matrix[self.vertices.index(toV)][self.vertices.index(fromV)] = cost

        self.edges_dict[(tail, head)] = cost
        self.edges_array.append((tail, head, cost))
        self.num_edges = len(self.edges_dict)

    def getEdges(self, V):
        pass

    def getVerticesNumbers(self):
        if self.num_vertices == 0:
            self.num_vertices = len(self.matrix)
        return self.num_vertices

    def getAllVertices(self):
        return self.vertices

    def getAllEdges(self):
        for i in range(len(self.matrix)):
            for j in range(len(self.matrix)):
                if 0 < self.matrix[i][j] < float('inf'):
                    self.edges_dict[self.vertices[i], self.vertices[j]] = self.matrix[i][j]
                    self.edges_array.append([self.vertices[i], self.vertices[j], self.matrix[i][j]])

        return self.edges_array

    def __repr__(self):
        return str(''.join(str(i) for i in self.matrix))

    def to_do_vertex(self, i):
        print('vertex: %s' % (self.vertices[i]))

    def to_do_edge(self, w, k):
        print('edge tail: %s, edge head: %s, weight: %s' % (self.vertices[w], self.vertices[k], str(self.matrix[w][k])))

def create_undirected_matrix(my_graph,matrix):
nodes = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 
             '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', 
             '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', 
             '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', 
             '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', 
             '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', 
             '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', 
             '71', '72', '73', '74', '75', '76', '77', '78', '79', '80',              
             ]
	my_graph = Graph_Matrix(nodes, matrix)
    print(my_graph)
    return my_graph       

有向图代码如下:

def create_directed_matrix(my_graph):#二维数组生成有向图
    nodes = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
    inf = float('inf')
    matrix = [[0, 2, 1, 3, 9, 4, inf, inf],  # a
              [inf, 0, 4, inf, 3, inf, inf, inf],  # b
              [inf, inf, 0, 8, inf, inf, inf, inf],  # c
              [inf, inf, inf, 0, 7, inf, inf, inf],  # d
              [inf, inf, inf, inf, 0, 5, inf, inf],  # e
              [inf, inf, 2, inf, inf, 0, 2, 2],  # f
              [inf, inf, inf, inf, inf, 1, 0, 6],  # g
              [inf, inf, inf, inf, inf, 9, 8, 0]]  # h

    my_graph = Graph_Matrix(nodes, matrix)
    print(my_graph)
    return my_graph

带权值的有向图代码如下:

def create_directed_graph_from_edges(my_graph):#用边生成有向图
    nodes = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
    edge_list = [('A', 'F', 9), ('A', 'B', 10), ('A', 'G', 15), ('B', 'F', 2),
                 ('G', 'F', 3), ('G', 'E', 12), ('G', 'C', 10), ('C', 'E', 1),
                 ('E', 'D', 7)]

    my_graph = Graph_Matrix(nodes)
    my_graph.add_edges_from_list(edge_list)
    print(my_graph)
    return my_graph

以上是参考大神思想出来的图的creat
但是当数据过大之后代入数据比较麻烦,于是我写了数据的导入函数,你可以实现把自己要导入的数据存入一个excel的不同子数据表中,通过调整不同带入参数实现变化数据的导入,本人是通过采用matlab循环处理数据导入excel中:实现代码如下:

def matrix(path):#读取excel表格里的数据
    table = xlrd.open_workbook(path).sheets()[6]    # 获取第6个sheet表
    row = table.nrows                               # 行数
    col = table.ncols                               # 列数
    datamatrix = np.zeros((row, col))               # 生成一个nrows行ncols列,且元素均为0的初始矩阵
    for x in range(col):
        try:
            cols = np.matrix(table.col_values(x))   # 把list转换为矩阵进行矩阵操作
            datamatrix[:, x] = cols                 # 按列把数据存进矩阵中
        except:
            print(x)
            
    print(datamatrix.shape)
    return datamatrix

各类图的显示代码如下:

def draw_undircted_graph(my_graph):#显示无向图
    G = nx.Graph()  # 建立一个空的无向图G
    for node in my_graph.vertices:
        G.add_node(str(node))
    for edge in my_graph.edges:
        G.add_edge(str(edge[0]), str(edge[1]))

    print("nodes:", G.nodes())  # 输出全部的节点: [1, 2, 3]
    print("edges:", G.edges())  # 输出全部的边:[(2, 3)]
    print("number of edges:", G.number_of_edges())  # 输出边的数量:1
    
    nx.draw(G, node_color = 'b',edge_color = 'r',with_labels=True)
    plt.savefig("undirected_graph.png")
    plt.show()

def draw_directed_graph(my_graph):#显示有向图,带权
    G = nx.DiGraph()  # 建立一个空的无向图G
    for node in my_graph.vertices:
        G.add_node(str(node))
    G.add_weighted_edges_from(my_graph.edges_array)

    print("nodes:", G.nodes())  # 输出全部的节点
    print("edges:", G.edges())  # 输出全部的边
    print("number of edges:", G.number_of_edges())  # 输出边的数量
    nx.draw(G, node_color = 'b',edge_color = 'r',with_labels=True)
    pos = spring_layout(G)
    plt.savefig("directed_graph.png")
    plt.show()

关于函数nx.draw的一点解释,nx.draw在库中的用法解释如下

"""Draw the graph G with Matplotlib.

    Draw the graph as a simple representation with no node
    labels or edge labels and using the full Matplotlib figure area
    and no axis labels by default.  See draw_networkx() for more
    full-featured drawing that allows title, axis labels etc.

    Parameters
    ----------
    G : graph
       A networkx graph

    pos : dictionary, optional
       A dictionary with nodes as keys and positions as values.
       If not specified a spring layout positioning will be computed.
       See :py:mod:`networkx.drawing.layout` for functions that
       compute node positions.

    ax : Matplotlib Axes object, optional
       Draw the graph in specified Matplotlib axes.

    kwds : optional keywords
       See networkx.draw_networkx() for a description of optional keywords.

    Examples
    --------
    >>> G = nx.dodecahedral_graph()
    >>> nx.draw(G)
    >>> nx.draw(G, pos=nx.spring_layout(G))  # use spring layout

    See Also
    --------
    draw_networkx()
    draw_networkx_nodes()
    draw_networkx_edges()
    draw_networkx_labels()
    draw_networkx_edge_labels()

    Notes
    -----
    This function has the same name as pylab.draw and pyplot.draw
    so beware when using `from networkx import *`

    since you might overwrite the pylab.draw function.

    With pyplot use

    >>> import matplotlib.pyplot as plt
    >>> import networkx as nx
    >>> G = nx.dodecahedral_graph()
    >>> nx.draw(G)  # networkx draw()
    >>> plt.draw()  # pyplot draw()

    Also see the NetworkX drawing examples at
    https://networkx.github.io/documentation/latest/auto_examples/index.html
    """

即你要对:

  • pos:字典–键值对进行定义,可选 以节点为键,位置为值的字典。
    -如果未指定,将计算弹簧布局定位。

  • 对于函数计算节点位置请参见:py:mod:网络X.drawing.layout ax:Matplotlib Axes对象(可选)

  • 还可以在指定的Matplotlib轴上绘制图形。
    -kwds:可选关键字

nx.draw(G,pos = nx.random_layout(G),node_color = 'b',edge_color = 'r',with_labels = True,font_size =18,node_size =20)
  • pos 指的是布局 主要有spring_layout , random_layout,circle_layout,shell_layout。node_color指节点颜色,有rbykw ,同理edge_color.表示边的颜色。
  • with_labels指节点是否显示名字,size表示大小,font_color表示字的颜色。
    在主函数中进行函数调用即可:
if __name__=='__main__':
    path = "E:\\my Python学习\\project test\\prac1\\pic\\pic\\data1.xls"
    datamatrix = matrix(path)
    my_graph=Graph_Matrix()
    created_graph=create_undirected_matrix(my_graph,datamatrix)
    draw_undircted_graph(created_graph)

全部源代码:传送门

“你是谁?”

“一个看帖子的人。”

“看帖子不点赞啊?”

“你点赞吗?”

“当然点了。”

“我也会点。”

“谁会把经验写在帖子里。”

“写在帖子里的那能叫经验贴?”

“上流!”

                                   cheer!!!

在这里插入图片描述

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大不怪将军

如果帮助到你,我很开心

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值