首页 > 编程语言 >Python如何使用Networkx实现复杂的人物关系图?

Python如何使用Networkx实现复杂的人物关系图?

时间:2023-11-18 11:32:13浏览次数:42  
标签:node None networkx 复杂 Python graph self Networkx my

(Python如何使用Networkx实现复杂的人物关系图?)

1 简单引入

  • 日常工作、生活中我们经常会遇到一些复杂的事务关系,比如人物关系,那如何才能清楚直观的看清楚这些任务关系呢?
  • 比如我们从网上搜索1个人物关系图,大家看看:

声明:以下图片来源于网络,如果涉及版权问题,请联系作者删除。本文仅供学习,不做他用。

在这里插入图片描述

  • 那我们如何使用Python来实现类似的人物关系图呢?
  • 这里我们需要用到Python的networkx模块,它可以帮助我们很好的显示我们需要的效果。

2 关于Networkx

2.1 Networkx简单说明

  • NetworkX是一个用于创建、操作和研究复杂网络的 Python 库;
  • 可以创建、分析和可视化各种类型的网络,例如社交网络、Web图、生物网络等;
  • NetworkX 可以用来创建各种类型的网络,包括有向图和无向图;
  • 提供各种方法来添加、删除和修改网络中的节点和边;
  • NetworkX 还提供许多图的算法和分析工具;
  • NetworkX还提供多种方式来可视化网络。

2.2 Networkx部分源码

  • NetworkX支持四种图,从以下源码可以看出:
Python37\Lib\site-packages\networkx\classes\__init__.py
from .graph import Graph
from .digraph import DiGraph
from .multigraph import MultiGraph
from .multidigraph import MultiDiGraph
from .ordered import *

from .function import *

from networkx.classes import filters

from networkx.classes import coreviews
from networkx.classes import graphviews
from networkx.classes import reportviews
  • 四种图即为:
说明
Graph 无多重边无向图
DiGraph 无多重边有向图
MultiGraph 有多重边无向图
MultiDiGraph 有多重边有向图
  • 而本文我们要用的是 Graph,它主要是用点和线来刻画离散事务集合,每对事务之间以某种方式相联系的数学模型;
  • Graph可以用来表示的关系图为人物关系图、流程图等等;
  • 以下为Graph的几个方法源码:
Python37\Lib\site-packages\networkx\classes\graph.py
def draw_networkx_nodes(
    G,
    pos,
    nodelist=None,
    node_size=300,
    node_color="#1f78b4",
    node_shape="o",
    alpha=None,
    cmap=None,
    vmin=None,
    vmax=None,
    ax=None,
    linewidths=None,
    edgecolors=None,
    label=None,
    margins=None,
):
    """Draw the nodes of the graph G.
def draw_networkx_edges(
    G,
    pos,
    edgelist=None,
    width=1.0,
    edge_color="k",
    style="solid",
    alpha=None,
    arrowstyle="-|>",
    arrowsize=10,
    edge_cmap=None,
    edge_vmin=None,
    edge_vmax=None,
    ax=None,
    arrows=None,
    label=None,
    node_size=300,
    nodelist=None,
    node_shape="o",
    connectionstyle="arc3",
    min_source_margin=0,
    min_target_margin=0,
):
    r"""Draw the edges of the graph G.
def draw_networkx_labels(
    G,
    pos,
    labels=None,
    font_size=12,
    font_color="k",
    font_family="sans-serif",
    font_weight="normal",
    alpha=None,
    bbox=None,
    horizontalalignment="center",
    verticalalignment="center",
    ax=None,
    clip_on=True,
):
    """Draw node labels on the graph G.
def circular_layout(G, scale=1, center=None, dim=2):
    # dim=2 only
    """Position nodes on a circle.

    Parameters
    ----------
    G : NetworkX graph or list of nodes
        A position will be assigned to every node in G.

    scale : number (default: 1)
        Scale factor for positions.

    center : array-like or None
        Coordinate pair around which to center the layout.

    dim : int
        Dimension of layout.
        If dim>2, the remaining dimensions are set to zero
        in the returned positions.
        If dim<2, a ValueError is raised.

2.3 Networkx一个示例

  • 比如一个几个节点的有向图:
# -*- coding: utf-8 -*-
import networkx as nx
import matplotlib.pyplot as plt

# 设置画布大小
plt.figure(figsize=(6, 7))

# 创建有向图对象
G = nx.DiGraph()

# 添加节点
my_node = ["nodeA", "nodeB", "nodeC", "nodeD", "nodeE", "nodeF"]
for node in my_node:
    G.add_node(node)

# 添加有向边
for edge in range(len(my_node)-1):
    print(edge)
    G.add_edge(my_node[edge], my_node[edge+1])

# 绘制
# 布局算法
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True)
plt.show()
  • 输出如下图示: 在这里插入图片描述

3 人物关系图绘制过程

3.1 创建原始数据

  • 我们以西游记和封神榜部分重点人物关系为例,先整理好一个任务关系excel文档relation.xls
character1	character2	color	       num	 relation
菩提祖师	    孙悟空	    antiquewhite	9	  第一任师傅
唐僧	        孙悟空	    aqua	        9	  师徒
如来佛祖	    孙悟空	    aquamarine	    9	  五指山
观音菩萨	    孙悟空	    azure	        9	  紧箍咒
牛魔王	    孙悟空	    beige	        9	  结拜兄弟
猪八戒	    孙悟空	    bisque	        9	  大师兄
沙和尚	    孙悟空	    black	        9	  大师兄
白龙马	    孙悟空	    blanchedalmond	9	  大师兄
孙悟空	    唐僧	        aliceblue	    6	  师徒
猪八戒	    唐僧	        bisque	        6	  师徒
沙和尚	    唐僧	        black	        6	  师徒
白龙马	    唐僧	        blanchedalmond	6	  师徒
观音菩萨	    唐僧	        azure	        6	  委派西天取经
老鼠精	    唐僧	        blue	        6	  欲嫁
老鼠精	    托塔天王	    blue	        4	  义父女
哪吒	        托塔天王	    blueviolet	    4	  父子
木吒	        托塔天王	    brown	        4	  父子
金吒	        托塔天王	    burlywood	    4	  父子
木吒	        观音菩萨	    brown	        2	  大弟子
红孩儿	    观音菩萨	    cadetblue	    2	  善财童子
金吒	        如来佛祖	    burlywood	    1	  前部护法
铁扇公主	    牛魔王	    darkkhaki	    2	  夫妻
红孩儿	    牛魔王	    cadetblue	    2	  父子
红孩儿	    铁扇公主	    cadetblue	    1	  母子
哪吒	        太乙真人	    blueviolet	    1	  师徒
太乙真人	    元始天尊	    chartreuse	    7	  师徒
云中子	    元始天尊	    chocolate	    7	  师徒
玉鼎真人	    元始天尊	    coral	        7	  师徒
王母娘娘	    元始天尊	    cornflowerblue	7	  父女
鸿钧老祖	    元始天尊	    cornsilk	    7	  师徒
姜子牙	    元始天尊	    crimson	        7	  师徒
太上老君	    鸿钧老祖	    cyan	        3	  师徒
灵宝天尊	    鸿钧老祖	    darkblue	    3	  师徒
雷震子	    云中子	    darkcyan	    1	  师徒
杨戬	        玉鼎真人	    darkgoldenrod	1	  师徒
沉香	        杨戬	        darkgray	    2	  舅舅
三圣母	    杨戬	        darkgreen	    2	  兄妹
元始天尊	    鸿钧老祖	    darkmagenta	    3	  师徒
托塔天王	    孙悟空	    darkgrey	    9	  上下级
  • 这里需要注意一点,人物的数量和颜色的数量要对应起来,不然会报错:
ValueError: 'c' argument has 23 elements, which is inconsistent with 'x' and 'y' with size 29.
  • 从上边的错误看,其实就是我的人物角色有29个,但是颜色只有23个,没有对应起来;
  • 为了避免错误,我们把人物和颜色列一个表,需要的时候选对应的数据就行:
孙悟空	    aliceblue
菩提祖师	    antiquewhite
唐僧	        aqua
如来佛祖	    aquamarine
观音菩萨	    azure
牛魔王	    beige
猪八戒	    bisque
沙和尚	    black
白龙马	    blanchedalmond
老鼠精	    blue
哪吒	        blueviolet
木吒	        brown
金吒	        burlywood
红孩儿	    cadetblue
太乙真人	    chartreuse
云中子	    chocolate
玉鼎真人	    coral
王母娘娘	    cornflowerblue
鸿钧老祖	    cornsilk
姜子牙	    crimson
太上老君	    cyan
灵宝天尊	    darkblue
雷震子	    darkcyan
杨戬	        darkgoldenrod
沉香	        darkgray
三圣母	    darkgreen
托塔天王	    darkgrey
铁扇公主	    darkkhaki
元始天尊	    darkmagenta

3.2 获取目标文件数据

  • 读取excel中的文件数据:
class TestRelation():
    def __init__(self):
        super(TestRelation, self).__init__()

        # 获取目标文件数据
        self.data = "./relation.xls"
        self.data_content = pd.DataFrame(pd.read_excel(self.data)) 
        self.character = self.data_content['character1'].drop_duplicates().values.tolist() 
        self.characters = self.data_content[['character1', 'character2', 'num']] 
  • 比如我们打印一下self.characters
0        菩提祖师        孙悟空    9
1          唐僧         孙悟空    9
2        如来佛祖        孙悟空    9
3        观音菩萨        孙悟空    9
4         牛魔王        孙悟空    9
5         猪八戒        孙悟空    9
6         沙和尚        孙悟空    9
7         白龙马        孙悟空    9
8         孙悟空         唐僧    6
9         猪八戒         唐僧    6
10        沙和尚         唐僧    6
11        白龙马         唐僧    6
12       观音菩萨         唐僧    6
13        老鼠精         唐僧    6
14        老鼠精       托塔天王    4
15         哪吒       托塔天王    4
16         木吒       托塔天王    4
17         金吒       托塔天王    4
18         木吒       观音菩萨    2
19        红孩儿       观音菩萨    2
20         金吒       如来佛祖    1
21       铁扇公主        牛魔王    2
22        红孩儿        牛魔王    2
23        红孩儿       铁扇公主    1
24         哪吒       太乙真人    1
25       太乙真人       元始天尊    7
26        云中子       元始天尊    7
27       玉鼎真人       元始天尊    7
28       王母娘娘       元始天尊    7
29       鸿钧老祖       元始天尊    7
30        姜子牙       元始天尊    7
31       太上老君       鸿钧老祖    3
32       灵宝天尊       鸿钧老祖    3
33        雷震子        云中子    1
34         杨戬       玉鼎真人    1
35         沉香         杨戬    2
36        三圣母         杨戬    2
37       元始天尊       鸿钧老祖    3
38       托塔天王        孙悟空    9

3.3 获取颜色数据

# 获取颜色数据
self.colors = self.data_content['color'].drop_duplicates().values.tolist()
print(self.colors)
  • 颜色获取如下:
['antiquewhite', 'aqua', 'aquamarine', 'azure', 
'beige', 'bisque', 'black', 'blanchedalmond', 
'aliceblue', 'blue', 'blueviolet', 'brown', 
'burlywood', 'cadetblue', 'darkkhaki', 'chartreuse',
'chocolate', 'coral', 'cornflowerblue', 'cornsilk',
 'crimson', 'cyan', 'darkblue', 'darkcyan', 
 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkmagenta', 'darkgrey']

3.5 添加边数据

self.my_graph = nx.Graph()
for i in self.characters.index:
    self.my_graph.add_edge(self.characters.character1[i],
                           self.characters.character2[i],
                           weight=self.characters.num[i])

3.6 定义边及权重

# 定义两个边,边给权重,s起点,e终点,w权重
edge1 = [(s, e) for (s, e, w) in self.my_graph.edges(data=True) if (w['weight'] >= 1)]
edge2 = [(s, e) for (s, e, w) in self.my_graph.edges(data=True) if (w['weight'] >= 5)]

3.7 图的布局、点、边和标签

# 图的布局
pos = nx.circular_layout(self.my_graph)

# 点
nx.draw_networkx_nodes(self.my_graph, pos, alpha=1, node_size=300,
                       node_color=self.colors, node_shape='o')

# 边
nx.draw_networkx_edges(self.my_graph, pos, edgelist=edge1, width=1,
                       alpha=0.3, edge_color='g', style='dashed')

nx.draw_networkx_edges(self.my_graph, pos, edgelist=edge2, width=1.5,
                        alpha=0.5, edge_color='red')
# 标签
nx.draw_networkx_labels(self.my_graph, pos, font_size=9)

3.8 展示结果

# 结果显示
plt.axis('off')
plt.title('西游记重点人物简单关系图(只是示例)')
plt.rcParams['font.size'] = 8

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.show()

3.9 完整源码

# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/11/16
# 文件名称:test_relation.py
# 作用:network应用
# 联系:VX(NoamaNelson)
# 博客:https://blog.csdn.net/NoamaNelson

import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt


class TestRelation():
    def __init__(self):
        super(TestRelation, self).__init__()

        # 获取目标文件数据
        self.data = "./relation.xls"
        self.data_content = pd.DataFrame(pd.read_excel(self.data))
        self.character = self.data_content['character1'].drop_duplicates().values.tolist()
        self.characters = self.data_content[['character1', 'character2', 'num']]
        print(self.characters)

    def test_relation(self):

        # 设置画布大小,可以使用默认的
        # plt.figure(figsize=(4, 5))

        # 获取颜色数据
        self.colors = self.data_content['color'].drop_duplicates().values.tolist()
        print(self.colors)

        self.my_graph = nx.Graph()
        # 添加边
        for i in self.characters.index:
            self.my_graph.add_edge(self.characters.character1[i],
                       self.characters.character2[i],
                       weight=self.characters.num[i])

        # 定义两个边,边给权重,s起点,e终点,w权重
        edge1 = [(s, e) for (s, e, w) in self.my_graph.edges(data=True) if (w['weight'] >= 1)]
        edge2 = [(s, e) for (s, e, w) in self.my_graph.edges(data=True) if (w['weight'] >= 5)]

        # 图的布局
        pos = nx.circular_layout(self.my_graph)

        # 点
        nx.draw_networkx_nodes(self.my_graph, pos, alpha=1, node_size=300,
                               node_color=self.colors, node_shape='o')

        # 边
        nx.draw_networkx_edges(self.my_graph, pos, edgelist=edge1, width=1,
                               alpha=0.3, edge_color='g', style='dashed')

        nx.draw_networkx_edges(self.my_graph, pos, edgelist=edge2, width=1.5,
                               alpha=0.5, edge_color='red')
        # 标签
        nx.draw_networkx_labels(self.my_graph, pos, font_size=9)

        # 结果显示
        plt.axis('off')
        plt.title('西游记重点人物简单关系图(只是示例)')
        plt.rcParams['font.size'] = 8
        plt.rcParams['font.sans-serif'] = ['SimHei']  # 解决中文乱码
        plt.show()


if __name__ == "__main__":
    relation = TestRelation()
    relation.test_relation()

4 人物关系效果图

  • 运行上边的完整源码得到如下效果: 在这里插入图片描述

标签:node,None,networkx,复杂,Python,graph,self,Networkx,my
From: https://blog.51cto.com/NoamaNelson/8460587

相关文章

  • Conda管理Python版本
    查看Python版本查看当前环境的Python版本condaactivate&&python-V查看指定环境condaactivatetest&&python-V创建Python环境先搜索conda有哪些python版本condasearch--full--namepython根据搜索出来的版本安装condacreate--nametestpython=3.9.7或......
  • 【小沐学Python】Web服务器搭建(Nginx、IIS)
    1、Web服务器web服务器一词可以代指硬件或软件,或者是它们协同工作的整体。6、NginxNginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器,同时也是一个IMAP、POP3、SMTP代理服务器,多用于高连接并发。6.1简介https://nginx.org/en/Nginx是lgorSysoev为俄罗斯......
  • Python | Opencv的人脸检测和人类识别
    ✅作者简介:热爱科研的算法开发者,Python、Matlab项目可交流、沟通、学习。......
  • python 赋值、浅拷贝、深拷贝的区别
    b=a: 赋值引用,a和b都指向同一个对象。b=a.copy(): 浅拷贝,a和b是一个独立的对象,但他们的子对象还是指向统一对象(是引用)。b=copy.deepcopy(a): 深度拷贝,a和b完全拷贝了父对象及其子对象,两者是完全独立的。对于可变的序列,切片操作符:是浅拷贝 比如:a=b[:]......
  • python:第十六章:赋值运算符
    一,什么是赋值运算符?赋值运算符的执行顺序赋值运算符=它用来把值赋给变量。运算符右边的表达式先计算得到结果,再将结果赋值给左边的变量12345#赋值x=5y=x+3print("x=",x)print("y=",y)运行结果:x=5y=8二,链式赋值就是同时给......
  • python:第十七章:布尔运算符(逻辑运算符)
    一,布尔运算符有哪些?and运算是与运算,只有两个值都为True,and运算结果才是True,如下表abaandbTrueTrueTrueTrueFalseFalseFalseTrueFalseFalseFalseFalseor运算是或运算,只要其中有一个值为True,or运算结果就是TrueabaorbTrueTrueT......
  • python:第十八章:比较运算符
    一,比较运算符是什么?用于比较两个值的运算符。作用:对两个值进行比较,并返回一个布尔值(True或False)作为比较的结果1,比较运算符有哪些主要有六种比较运算符:小于(<)小于等于(<=)大于(>)大于等于(>=)等于(==)不等于(!=)2,字符串的比较规则:按字母的顺序比较:顺序越靠前则值越小,顺......
  • python:第十九章:数据类型之None
    一,什么是None?None表示空值,其类型为NoneType,内存中值为None的对象是同一个实例123456789#None的类型print("None的类型:",type(None)) #输出<class'NoneType'> #值为None的对象是同一个实例,#由于内存None只有一个,所以aisb的结果为True......
  • python:第二十章:数据类型转换之bool
    一,如何得到对象的布尔值?Python中,所有的数据都是对象,如整数、浮点数、字符串、列表、字典等。每个对象都有一个布尔值,用于表示对象的真假内置函数bool()能用来获取对象的布尔值。它把对象转换为布尔值,返回True或False,表示对象为真或假看例子:非0数字的布尔值为True,0的布尔值......
  • 代码随想训练营第三十七天(Python)| 738.单调递增的数字、968.监控二叉树
    738.单调递增的数字classSolution:defmonotoneIncreasingDigits(self,n:int)->int:#主要思路当前数字比前面数字小时。前面数字-1,当前数字变2为9str_n=str(n)foriinrange(len(str_n)-1,0,-1):ifstr_n[i]<str_n[......