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

简介: 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 人物关系效果图

  • 运行上边的完整源码得到如下效果:
    在这里插入图片描述
目录
相关文章
|
5月前
|
存储 程序员 Python
小白也能用的代码!1行Python,把PPT转成1张长图
大家好,我是程序员晚枫。今天介绍`python-office`库的新功能:仅用1行Python代码将PPT转为单张长图。
87 11
 小白也能用的代码!1行Python,把PPT转成1张长图
|
5月前
|
机器学习/深度学习 算法 TensorFlow
|
5月前
|
算法 Python
Python 大神修炼手册:图的深度优先&广度优先遍历,深入骨髓的解析
【7月更文挑战第12天】Python进阶必学:DFS和BFS图遍历算法。理解图概念,用邻接表建无向图,实现DFS和BFS。DFS适用于查找路径,BFS解决最短路径。通过实例代码加深理解,提升编程技能。
47 4
|
5月前
|
算法 Python
逆袭之路!用 Python 玩转图的 DFS 与 BFS,让数据结构难题无处遁形
【7月更文挑战第12天】图的遍历利器:DFS 和 BFS。Python 中,图可表示为邻接表或矩阵。DFS 沿路径深入,回溯时遍历所有可达顶点,适合找路径和环。BFS 层次遍历,先近后远,解决最短路径问题。两者在迷宫、网络路由等场景各显神通。通过练习,掌握这些算法,图处理将游刃有余。
67 3
|
4月前
|
自然语言处理 数据可视化 Python
【Python】Python人民的名义-词云-关系图可视化(源码+报告)【独一无二】
【Python】Python人民的名义-词云-关系图可视化(源码+报告)【独一无二】
|
5月前
|
存储 算法 Python
“解锁Python高级数据结构新姿势:图的表示与遍历,让你的算法思维跃升新高度
【7月更文挑战第13天】Python中的图数据结构用于表示复杂关系,通过节点和边连接。常见的表示方法是邻接矩阵(适合稠密图)和邻接表(适合稀疏图)。图遍历包括DFS(深度优先搜索)和BFS(广度优先搜索):DFS深入探索分支,BFS逐层访问邻居。掌握这些技巧对优化算法和解决实际问题至关重要。**
51 1
|
5月前
|
存储 算法 搜索推荐
Python高手必备!揭秘图(Graph)的N种风骚表示法,让你的代码瞬间高大上
【7月更文挑战第10天】在Python中,图数据结构通过邻接矩阵、邻接表、边列表和邻接集来表示,用于社交网络分析和路径查找等。邻接矩阵用二维数组存储连接,邻接表仅存储每个节点的邻居,节省空间。边列表列出所有边,而邻接集用集合确保邻居唯一性。选择合适表示法能提升代码效率和可读性,展现编程技巧。
82 1
|
6月前
|
机器学习/深度学习 数据采集 TensorFlow
使用Python实现深度学习模型:图神经网络(GNN)
使用Python实现深度学习模型:图神经网络(GNN)
361 1
|
5月前
|
数据可视化 Python
Python中绘制3D曲面图的艺术
【7月更文挑战第4天】使用Python的Matplotlib和mpl_toolkits.mplot3d库,可以轻松绘制3D曲面图。首先安装matplotlib,然后导入numpy和相关模块。通过定义函数和使用numpy的meshgrid生成数据,接着用`plot_surface`绘制曲面,可定制色彩映射、添加标签、标题、色标、透明度和阴影。通过自定义颜色映射和添加网格线,能进一步增强图形的解读性。这些技巧使3D数据可视化更具洞察力和吸引力。
105 0
|
6月前
|
Python
Python包 - networkx详细拆解
Python包 - networkx详细拆解
51 0
下一篇
DataWorks