3.2 基础网络
实际生活中的复杂系统大多以复杂网络的形式存在,大多数系统都包括多个子系统和连接,而传统的数字和表格形式组织数据的方式,使得人们很难对复杂网络有整体上的认识。对于复杂网络研究来说,可视化技术十分重要,它有助于呈现或解释复杂网络数据和结构,进而从中发现(或许是从数据中不易发现的)各种模式、特点和关系。
1.导入Pymnet库
下面简单介绍Python 的多层网络库Pymnet的使用。首先代码的第一行就要导入Pymnet模块。使用的代码如下:
![]()
2.网络基础结构
在Pymnet中,Multilayer Network是库中的基本网络类,所有其他类型的网络都是它的特例。
(1)网络
①在画图的第一步,首先要建立一个网络。一般来说,简单地构造一个又一个切面(aspect)的多层网络,建立一个单一的网络对象就可以满足人们的需求。代码如下:
![]()
②Pymnet库可以直接建立经典网络模型中的ER 网络,使用下面的语句就可以建立一个ER 网络:

③Pymnet还支持邻接矩阵输入,可以根据已有的数据集绘制网络。这会在3.2.3的数据集可视化小节中详细讲解。代码如下:

(2)网络层
Pymnet是可以用来绘制多层网络的库,用户可以采用add_layer(layer)方法添加网络层,示例如下:
![]()
(3)节点和边
图可以以多种方式进行增长。Pymnet提供多个功能用于读写图,访问网络的连边和节点,可以用以下的方法对网络中的节点和边进行操作:

(4)度
在复杂网络中,节点的度是重要的基本概念。Pymnet提供以下方法对网络中节点度进行处理:

(5)邻居
邻居节点也是复杂网络中的重要基本概念,在Pymnet可以用以下方法查看:
![]()
3.网络可视化
Pymnet库可以生成多层和多路网络的高质量图像。在库中生成网络映像的主要方法是使用Matplotlib作为后端。这些图像可以以矢量格式(如pdf或svg)和光栅格式(如png)保存。或者可以使用Javascript和D3作为显示图形后端的方法生成网络图片。这些交互式图形可以在任何现代浏览器中查看。
(1)基本绘图流程
在Pymnet 中,绘制一个网络使用draw()方法,它可用来绘画多层网络,使用Matplotlib绘制多层网络的3D 图片。它至少接受一个参数:即用户希望绘制的网络net。后边会介绍一些常用的参数,本书先从最简单的情况入手,看看下边的例子。

运行上述代码的结果如图3-2所示。

图3-2 源文件的目录下生成了一个png文件
(2)运用样式
上边的代码虽然简单,但生成的图形略显单调。Pymnet提供了一系列样式参数,可以用来修饰和美化图形,达到人们想要的效果。常用的参数包括:

1)布局
为了使网络看起来更方便,符合用户的要求。Pymnet在绘制网络图形方面提供了布局的功能,可以指定节点排列的形式。这些布局包括:

除random 和spring外,其余布局节点顺序位置固定。
2)层的形状
根据用户的不同需求,Pymnet提供了两种网络层的形状:rectangle正方形和circle圆形。
3)属性
各种可见元素可以使用一个属性设置方案来设置值,类似于下面的常见属性:layerColor;layer Label;nodeLabel;nodeSize;nodeColor;edgeColor;edgeWidth;edgeStyle(图层颜色、图层标签、节点标签、节点大小、节点颜色、边缘颜色、边缘宽度和边缘样式)。
每个属性都有三个可用于设置元素值的参数:[property]Dict、[property]Rule 和default[property](此处的单词[property]被属性名称替换)。
每个参数都可以设置元素的属性,这些参数按照[property]Dict、[property]Rule和default[property]的顺序遍历,直到找到属性值为止。
![]()
等号后面是默认值。
![]()
字典给每个元素一个属性值。键是元素,值是属性值。
元组表示:(1,'a')表示层a节点1;((1,'a'),(2,'b'))表示层a节点1和层b节点2之间的边。
![]()
通过给出一个确定属性值的规则来设置属性值。规则可以是通用的,也可以是特定于属性类型的。例如,使用节点度作为属性值是特定于节点属性的,如节点大小或节点颜色。空属性字典表示没有规则用于设置属性,可以通过向属性规则字典中添加一个项来设置规则,并将rule和特定规则作为键和值。
①通用属性:
order:对象的迭代器给出属性值的顺序。
name:对象名称用作属性的值。
节点属性(节点颜色、节点标签、节点大小):
degree:节点的度。
节点标签属性:
nodename:节点的名称(“name”为节点-层元组)。
边的属性(边的颜色,边的宽度,边的样式)。
edgetype:属性是根据边的类型给出的。可以在属性规则字典中包含键intra和/或inter,以给出层内边和层间边的值。
edgeweight:边的权重。
②属性修饰符:
在将规则生成的属性指定为元素的最终属性之前,可以对它们进行修改,这是由属性修饰符完成的。属性修饰符可以堆叠在一起,它们的遍历顺序与引入它们的顺序相反。每个属性修饰符都是属性规则字典中的一个项。
·通用的修饰符:
colormap:使用Matplotlib色彩图将数字映射到颜色。值是色彩图的名称,例如jet。
·色彩图分类:
Sequential:顺序。通常使用单一色调,逐渐改变亮度式使颜色渐渐增加。应该用于表示有顺序的信息。
名称:'viridis','plasma','inferno','magma','cividis','Greys','Purples','Blues','Greens','Oranges','Reds','YlOrBr','YlOr Rd','OrRd','PuRd','RdPu','BuPu','GnBu','PuBu','YlGnBu','PuBuGn','BuGn','YlGn' ,'binary','gist_yarg','gist_gray','gray','bone','pink','spring','summer','autumn','winter','cool','Wistia','hot','afmhot','gist_heat','copper'。
Diverging:发散。改变两种不同颜色的亮度和饱和度,这些颜色在中间以不饱和的颜色相遇;当绘制的信息具有关键中间值(例如地形)或数据偏离零时,应使用此值。
名称:'PiYG','PRGn','Br BG','Pu Or','Rd Gy','Rd Bu','Rd YlBu','Rd Yl Gn','Spectral','coolwarm','bwr','seismic'。
Cyclic:循环。改变两种不同颜色的亮度,在中间和开始/结束时以不饱和的颜色相遇。应该用于在端点处环绕的值,例如相角,风向或一天中的时间。
名称:'twilight','twilight_shifted','hsv'。
Qualitative:定性。常是杂色,用来表示没有排序或关系的信息。
名称:'Pastel1','Pastel2','Paired','Accent','Dark2','Set1','Set2','Set3','tab10','tab20','tab20b','tab20c'。
Miscellaneous:杂色。
名称:'flag','prism','ocean','gist_earth','terrain','gist_stern','gnuplot','gnuplot2','CMRmap','cubehelix','brg','gist_rainbow','rainbow','jet','nipy_spectral','gist_ncar'。
例子:layerColor Rule={“rule”:”name”,"colormap":"Pastel1"}。
scaleby:将属性值乘以一个给定的常数。
edgeWidthRule={'rule':'edgeweight',"scaleby":1.5}#按照边的权重规定边的宽度
f:任何函数都将该值作为参数并返回修改后的值。
·节点大小修饰符:
propscale:将每一项乘以一个给定的常数,然后除以网络中节点数的平方根。
(3)样式示例
1)颜色
用户可以通过属性参数设置层、点和连边的颜色。
①层的颜色
如果用户想统一所有网络层的颜色,可以规定层的默认颜色,示例如下:(https://www.daowen.com)
draw(net,default LayerColor="pink")#此网络所有层的颜色为粉色,结果如图3-3所示。
用户也可以用下面的方法指定某层的颜色:
draw(net,layerColor Dict={0:"gray",1:"pink"})#将第0层颜色设为灰色,第1层颜色设为粉色,结果如图3-4所示。

图3-3 规定所有层的默认颜色

图3-4 指定某层的颜色
为了方便用户,Pymnet还提供了一些着色规则,用户可以按某规则并用色彩图给所有层着色。示例如下:
draw(net,layer Color Rule= {'rule' :'name' ,"colormap":"Pastel1"})#按照Pastel1色彩图给每层依次着色,结果如图3-5所示。
②点的颜色
Pymnet中还可以更改点的颜色,如果用户想统一所有节点的颜色,可以规定节点的默认颜色,示例如下:
draw(net,default NodeColor="red")#此网络所有节点的颜色为红色,结果如图3-6所示。

图3-5 按某规则并用色彩图给所有层着色

图3-6 规定所有节点的默认颜色
用户还可以用下面的方法指定某节点的颜色:
draw(net,nodeColor Dict={(1,0):"red"})#将0层节点1设为红色,结果如图3-7所示。
③边的颜色
如果用户想统一所有网络中边的颜色,可以规定边的默认颜色,示例如下:
draw(net,defaultEdgeColor="pink")#此网络所有连边的颜色为粉色,结果如图3-8所示。

图3-7 指定某节点的颜色

图3-8 规定所有连边的默认颜色
用户也可以用下面的方法指定某条边的颜色:
draw(net,edgeColor Dict={((2,0),(3,0)):"pink"})#将0层节点2和3之间的边设为粉色,结果如图3-9所示。
用户还可以按某规则用色彩图给所有连边着色。代码如下:

2)节点大小
用户可以通过属性参数设置节点大小。也可以按照需求指定某节点的大小,示例如下:
draw(net,nodeSizeDict={(1,0):0.1,(3,0):0.05}) #将0层节点1大小设为0.1,0层节点3大小设为0.05,结果如图3-10所示。

图3-9 指定某条边的颜色

图3-10 指定某节点的大小
Pymnet提供了规则参数,可以按某规则设置图中节点大小,示例如下:
draw(net,nodeSizeRule= {"rule":"degree","propscale":0.1})#根据节点的度决定节点大小,结果如图3-11所示。
3)边的宽度
用户可以通过属性参数设置连边的宽度。
如果用户想统一网络中所有边的宽度,可以规定边的默认宽度,示例如下:
draw(net,default EdgeWidth=2)#此网络所有连边的宽度设为2,结果如图3-12所示。

图3-11 按某规则设置图中节点大小

图3-12 规定所有连边的默认宽度
用户还可以按照下面的方法指定某条边的宽度:
draw(net,edgeWidth Dict={((2,0),(3,0)):4})#将0层节点1和2之间的边的宽度设为4,结果如图3-13所示。
Pymnet提供了规则参数,可以按某规则设置图中边的宽度,示例如下:
draw(net,edgeWidthRule= {"rule":"edgeweight","scaleby":1.5})#根据边的权重设置连边的宽度。
4)标签
用户可以通过属性参数设置层和节点的标签。
①层的标签
Pymnet默认用数字作为层的标签,用户可以按照需求更改某层的标签,示例如下:
draw(net,layer Label Dict={0:'a'})#将0层标签改为a,结果如图3-14所示。

图3-13 指定某条边的宽度

图3-14 更改某层的标签
Pymnet还可以隐藏层的标签,示例如下:
draw(net,layer LabelRule={})#隐藏所有层的标签,结果如图3-15所示。
②节点标签
Pymnet默认用数字作为节点的标签,用户可以按照需求更改某节点的标签,示例如下:
draw(net,node LabelDict={(0,0):'a'})#将0层节点0的标签改为a,结果如图3-16所示。

图3-15 隐藏层的标签

图3-16 更改某节点的标签
Pymnet还可以隐藏所有节点标签,示例如下:
draw(net,node Label Rule={})#隐藏所有节点标签,结果如图3-17所示。

图3-17 隐藏所有节点标签
(4)数据集可视化
Pymnet还支持读取网络数据集文件,这里用到read_ucinet(netinput,couplings=('categorical',1.0),fullyInterconnected =True)方法。其中,参数netinput为读取的网络文件名,可以是bat或txt格式;参数couplings为层间耦合连边,在较大网络中一般设为none;参数fullyInterconnected 判断是否显示网络中度为0的节点,True为显示,False为不显示。
网络文件是UCINET DL格式。以Bernard&Killworth fraternity network数据集为例,对应bkfrat.dat文件,链接为http://vlado.fmf.uni-lj.si/pub/networks/data/ucinet/ucidata.htm#bkfrat。
DL
N=58 NM=2
FORMAT=FULLMATRIX DIAGONAL PRESENT
LEVEL LABELS:
BKFRAB
BKFRAC
DATA:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX(邻接矩阵)
DL是文件识别头,N 是节点,NM 是层数,format是文件格式,可以是edgelist,也可以是邻接矩阵。level labels下面的是层的名字,data下面是对应的邻接矩阵。
示例代码:

结果如图3-18所示。

图3-18 bkfrat.dat数据集的可视化效果