网络数据统计分析笔记|| 操作网络数据

网络数据统计分析笔记|| 操作网络数据_第1张图片

前情回顾:
Gephi网络图极简教程
Network在单细胞转录组数据分析中的应用
网络数据统计分析笔记|| 为什么研究网络

书接上回,我们来看看如何构建网络以及可以对网络做的基本操作,主要用的R包是igraph。

  • 创建网络图
  • 图的表示
  • 图的增删
  • 图的修饰
  • 图的属性
网络数据统计分析笔记|| 操作网络数据_第2张图片

igraph是一个用于创建和操作图以及分析网络的R包。它是用C编写的,也以Python和R包的形式存在。此外,还存在一个Mathematica接口。该软件广泛应用于网络科学及相关领域的学术研究。据谷歌Scholar统计,截止2015年6月5日,介绍该软件的出版物有5623次引用。

创建网络图

网络用节点描述元素,用连线描述元素间关系。一个图是包含节点集合与边集合的数学结构。其中节点数称为图的阶数(order),边的数量称为图的规模(size)。

在创建图之前我们来认识一下igraph包。

# install.packages("pacman")
rm(list = ls())
library(sand)

# CHUNK 1
library(igraph)
library(pacman)
length(p_functions(igraph))
[1] 784
 grep('graph_from',p_functions(igraph),value = T)
 [1] "graph_from_adj_list"          "graph_from_adjacency_matrix"  "graph_from_atlas"            
 [4] "graph_from_data_frame"        "graph_from_edgelist"          "graph_from_graphdb"          
 [7] "graph_from_graphnel"          "graph_from_incidence_matrix"  "graph_from_isomorphism_class"
[10] "graph_from_lcf"               "graph_from_literal"          

可以看到igraph 共有 784个函数,其中读入数据的有11个,功能可谓是全的很啊。我们先从最简单的做起,构建一个手写的图:

g <- graph_from_literal(1-2, 1-3, 2-3, 2-4, 3-5, 4-5, 
                    4-6, 4-7, 5-6, 6-7)

plot(g)
网络数据统计分析笔记|| 操作网络数据_第3张图片

查看图的属性

 V(g)
+ 7/7 vertices, named, from e2c1098:
[1] 1 2 3 4 5 6 7

 E(g)
+ 10/10 edges from e2c1098 (vertex names):
 [1] 1--2 1--3 2--3 2--4 3--5 4--5 4--6 4--7 5--6 6--7

 print_all(g)
IGRAPH e2c1098 UN-- 7 10 -- 
+ attr: name (v/c)
+ edges (vertex names):
1 -- 2, 3
2 -- 1, 3, 4
3 -- 1, 2, 5
4 -- 2, 5, 6, 7
5 -- 3, 4, 6
6 -- 4, 5, 7
7 -- 4, 6

在g的结构描述中,字母U表示该图是无向的(undirected),即一条边的两个节点没方向和次序。简单有向图可以这样构建:

dg <- graph_from_literal(1-+2, 1-+3, 2++3)
plot(dg)
网络数据统计分析笔记|| 操作网络数据_第4张图片

要想使图有意义,我们就需要给图起名字:

 par(mfrow=c(1,3))
dg <- graph_from_literal(1-+2, 1-+3, 2++3)
plot(dg)
dg <- graph_from_literal(Sam-+Mary, Sam-+Tom, 
+                           Mary++Tom)
 print_all(dg)

IGRAPH ea00245 DN-- 3 4 --  # UN 变成DN
+ attr: name (v/c)
+ edges from ea00245 (vertex names):
[1] Sam ->Mary Sam ->Tom  Mary->Tom  Tom ->Mary

 plot(dg)

V(dg)$name <- c("Sam1", "Mary1", "Tom_1")

E(dg)
+ 4/4 edges from ea00245 (vertex names):
[1] Sam1 ->Mary1 Sam1 ->Tom_1 Mary1->Tom_1 Tom_1->Mary1
> # ---
> ## + 4/4 edges from 062bf79 (vertex names):
> ## [1] Sam ->Mary Sam ->Tom  Mary->Tom  Tom ->Mary
> # ---
 plot(dg)
网络数据统计分析笔记|| 操作网络数据_第5张图片

我们无法想象手动用+-号来构建一个成千上百的网络图,一般的图都是在数据文件里,存在三种表示图的格式:

  • 邻接列表
  • 边列表
  • 邻接矩阵

邻接表(graph_adjacency_list):邻接表是图的一种链式存储结构。在邻接表中,对图中每一个顶点建立一个单链表,第i个单链表中的节点表示依附于顶点vi的边(对有向图是以顶点vi为尾的弧)。每一个结点有三个域组成,当中邻接点域指示与顶点vi邻接的点在途中的位置,链域指示下一条边或者弧的结点;数据域存储和边或者弧相关的信息。如权值等。每一个链表上附设一个表头结点。

边列表简单来说就是边跟边的两个顶点。

 E(dg)
+ 4/4 edges from ea00245 (vertex names):
[1] Sam1 ->Mary1 Sam1 ->Tom_1 Mary1->Tom_1 Tom_1->Mary1

图的邻接矩阵存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中的边或弧的信息。
设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为:


as_adjacency_matrix(dg)
3 x 3 sparse Matrix of class "dgCMatrix"
      Sam1 Mary1 Tom_1
Sam1     .     1     1
Mary1    .     .     1
Tom_1    .     1     .

三者之间的对应 关系可以用下图表示:

网络数据统计分析笔记|| 操作网络数据_第6张图片

鉴于矩阵是多数编程语言的基本数据对象,邻接矩阵经常作为网络图的存储方式。但是如果是大型的网络,如果不转化为稀疏矩阵,一般的矩阵会非常低效。在文章的开头我们展示了几个其他数据读入igraph的函数,以生成对应的网络。read_graph函数能够从文件或http连接读取各种表示形式的图形。

igraph绘制的网络图导入到gephi

 install and load
install.packages("rgexf", dependencies=TRUE)
library(rgexf)  
cg1 <- erdos.renyi.game(10, 0.8)
nodes <- data.frame(cbind(V(cg1), as.character(V(cg1))))
edges <- t(Vectorize(get.edge, vectorize.args='id')(cg1, 1:ecount(cg1)))
write.gexf(nodes, edges) 

图的表示

刚生成或者导入的图可能不是我们需要的图,对图的各种操作不可或缺,包括取子图、删节点,增加边,甚至是合并图。在一张图上有了感兴趣的区域,我们一般会采取取子图的操作,子图的定义是某图的边和点均来自母图。如取g前5个节点的子图:

 h <- induced_subgraph(g, 1:5)
print_all(h)
IGRAPH ae29f26 UN-- 5 6 -- 
+ attr: name (v/c)
+ edges from ae29f26 (vertex names):
[1] 1--2 1--3 2--3 2--4 3--5 4--5
 plot(h)
网络数据统计分析笔记|| 操作网络数据_第7张图片

图中节点和边的纳入与删除,可以通过对集合和使用加号或减号操作符实现。上面的图可以:

h <- g - vertices(c(6,7))
print_all(h)
plot(h)
网络数据统计分析笔记|| 操作网络数据_第8张图片

相似地,g也可以由h生成:

 h <- h + vertices(c(6,7))
 g <- h + edges(c(4,6),c(4,7),c(5,6),c(6,7))
print_all(g)
IGRAPH 77655ae UN-- 7 10 -- 
+ attr: name (v/c)
+ edges (vertex names):
1 -- 2, 3
2 -- 1, 3, 4
3 -- 1, 2, 5
4 -- 2, 5, 6, 7
5 -- 3, 4, 6
6 -- 4, 5, 7
7 -- 4, 6
plot(g)
网络数据统计分析笔记|| 操作网络数据_第9张图片

图的并,交,差,补。
图的并集

h1 <- h
h2 <- graph_from_literal(4-6, 4-7, 5-6, 6-7)
g <- graph.union(h1,h2)
print_all(g)
IGRAPH 1cc06a7 UN-- 7 10 -- 
+ attr: name (v/c)
+ edges (vertex names):
1 -- 2, 3
2 -- 1, 3, 4
3 -- 1, 2, 5
4 -- 2, 5, 6, 7
5 -- 3, 4, 6
6 -- 4, 5, 7
7 -- 4, 6
plot(g)
网络数据统计分析笔记|| 操作网络数据_第10张图片
网络图的修饰

一幅图(graph,network)要有实际的意义,就要有与相应的网络图所关联的值。将一个图与这些属性(attributes)关联在一起的过程称为图的修饰(decorating)。在igraph中节点和边的属性可以通过$符号获得和修改。

V(dg)$name
[1] "Sam"  "Mary" "Tom" 
V(dg)$gender <- c("M","F","M")

V(g)$color <- c("red","blue")
plot(g)

网络数据统计分析笔记|| 操作网络数据_第11张图片

也可以将某些计算的节点特征值用这种方式保存,并用于可视化化或者统计。

同样地,边的属性用于描述元素之间的关系,如强弱,正负等。边的属性在在许多分析中可以认为是权重,有权重的图称为含权图(weighted graph)。

 is_weighted(g)
[1] FALSE

wg <- g
E(wg)$weight <- runif(ecount(wg))
 is_weighted(wg)
[1] TRUE
 plot(wg)
网络数据统计分析笔记|| 操作网络数据_第12张图片

其实图本身也可以有属性,如:

g$name <- "Toy Graph"

使用数据框

大型的网络图不可能手动输入,而是采用数据框来存储和读入。igraph的节点和边属性可以存在节点和边文件的数据框中。

library(sand)
head(elist.lazega)
  V1  V2
1 V1 V17
2 V2  V7
3 V2 V16
4 V2 V17
5 V2 V22
6 V2 V26
head(v.attr.lazega)
  Name Seniority Status Gender Office Years Age Practice School
1   V1         1      1      1      1    31  64        1      1
2   V2         2      1      1      1    32  62        2      1
3   V3         3      1      1      2    13  67        1      1
4   V4         4      1      1      1    31  59        2      3
5   V5         5      1      1      2    31  59        1      2
6   V6         6      1      1      2    29  55        1      1

> g.lazega <- graph_from_data_frame(elist.lazega,
+                                    directed="FALSE",
+                                    vertices=v.attr.lazega)
> g.lazega$name <- "Lazega Lawyers"
> # CHUNK 21
> vcount(g.lazega)
[1] 36
> # CHUNK 22
> ecount(g.lazega)
[1] 115
> # CHUNK 23
> vertex_attr_names(g.lazega)
[1] "name"      "Seniority" "Status"    "Gender"    "Office"    "Years"     "Age"       "Practice"  "School"   
> # ---
> ## [1] "name"      "Seniority" "Status"    "Gender"   
> ## [5] "Office"    "Years"     "Age"       "Practice" 
> ## [9] "School"
> # ---
> plot(g.lazega)

网络数据统计分析笔记|| 操作网络数据_第13张图片
V(g.lazega)$color  = V(g.lazega)$Seniority
plot(g.lazega)
网络数据统计分析笔记|| 操作网络数据_第14张图片
关于图

简单图:在无向图中,关联一对顶点的无向边如果多于1条,则称这些边为平行边,平行边的条数称为重数。在有向图中,关联一对顶点的有向边如果多于1条,并且这些边的始点与终点相同(也就是它们的的方向相同),称这些边为平行边。含平行边的图称为多重图,既不含平行边也不包含自环的图称为简单图。

is_simple(g)
[1] TRUE

构建多重图

mg <- g + edge(2,3)
 is_simple(mg)
[1] FALSE
    
print_all(mg)
plot(mg)
网络数据统计分析笔记|| 操作网络数据_第15张图片

在网络数据分析中,常需要将多重图转化为加权的简单图:

E(mg)$weight <- 1
# plot(mg)
# ?simplify
wg2 <- igraph::simplify(mg)
is_simple(wg2)
[1] TRUE

print_all(wg2)
IGRAPH c219b27 UNW- 7 10 -- 
+ attr: name (v/c), color (v/c), weight (e/n)
+ edges (vertex names):
1 -- 2, 3
2 -- 1, 3, 4
3 -- 1, 2, 5
4 -- 2, 5, 6, 7
5 -- 3, 4, 6
6 -- 4, 5, 7
7 -- 4, 6

E(wg2)$weight
 [1] 1 1 2 1 1 1 1 1 1 1

plot(wg2)

网络数据统计分析笔记|| 操作网络数据_第16张图片

图的连通性,如果两个节点之间通过一条边链接,我们称两者是邻接的(adjacent),这些节点可以称为邻居(neighbors)。

neighbors(g,5)

+ 3/7 vertices, named, from 1cc06a7:
[1] 3 4 6

类似地,两条边通过一个节点相连,称两者是邻接的。节点的度(degree)定义为其关联的边的数量。

degree(g)
1 2 3 4 5 6 7 
2 3 3 4 3 3 2 

如果是有向图,节点度可以进一步分为入度(in-degree)与出度(out-degree)分别代表指向与离开节点边的数量。

degree(dg, mode="in")
 Sam Mary  Tom 
   0    2    2 

 degree(dg, mode="out")
 Sam Mary  Tom 
   2    1    1 

描述图移动的概念:

通路(walk)是一个节点和边交替的序列
通路的长度length
不存在重复边的通路为迹(trail)
不存在重复节点的通路为路径(path)
起点和终点相同的迹为回路(circuit)

如果图中存在节点到另一个节点的一条通路,则可称节点到是可达的(reachable),若所有节点从任意节点均可达,则称图是连通的(connected)。图的组件(component)是一个最大化的连通子图。

is_connected(g)
[1] TRUE

 clusters(g)
$membership
1 2 3 4 5 6 7 
1 1 1 1 1 1 1 

$csize
[1] 7

$no
[1] 1

对于有向图,有弱连通和强连通之别:

 is_connected(dg,mode="weak")
[1] TRUE

is_connected(dg,mode="strong")
[1] FALSE

图中节点的距离(distance),被定义为节点间最短路径长度。图中最长的距离的值称为直径(diameter)

diameter(g, weights=NA)
[1] 3
特殊类型的图
g.full <- make_full_graph(7)
g.ring <- make_ring(7)
g.tree <- make_tree(7, children=2, mode="undirected")
g.star <- make_star(7, mode="undirected")
par(mfrow=c(2, 2), mai = c(0.2, 0.2, 0.2, 0.2))
plot(g.full,main='compele graph')
plot(g.ring,main= 'regular graph')
plot(g.tree,main='tree')
plot(g.star,main='star')
网络数据统计分析笔记|| 操作网络数据_第17张图片

一个无环的有向图称做有向无环图(directed acycline praph)。简称DAG 图。DAG 图是一类较有向树更一般的特殊有向图。

is_dag(dg)
[1] FALSE

二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。

g.bip <- graph_from_literal(actor1:actor2:actor3,
   movie1:movie2, actor1:actor2 - movie1,
   actor2:actor3 - movie2)
V(g.bip)$type <- grepl("^movie", V(g.bip)$name)
print_all(g.bip, v=T)

IGRAPH f306940 UN-B 5 4 -- 
+ attr: name (v/c), type (v/l)
+ vertex attributes:
|       name  type
| [1] actor1 FALSE
| [2] actor2 FALSE
| [3] actor3 FALSE
| [4] movie1  TRUE
| [5] movie2  TRUE
+ edges from f306940 (vertex names):
[1] actor1--movie1 actor2--movie1 actor2--movie2 actor3--movie2

图的投影

proj <- bipartite_projection(g.bip)
print_all(proj[[1]])
IGRAPH 9a82b4d UNW- 3 2 -- 
+ attr: name (v/c), weight (e/n)
+ edges from 9a82b4d (vertex names):
[1] actor1--actor2 actor2--actor3

print_all(proj[[2]])
IGRAPH 9a82b4d UNW- 2 1 -- 
+ attr: name (v/c), weight (e/n)
+ edge from 9a82b4d (vertex names):
[1] movie1--movie2

par(mfrow=c(1, 3), mai = c(0.2, 0.2, 0.2, 0.2))
plot(g.bip)
plot(proj[[1]])
plot(proj[[2]])
网络数据统计分析笔记|| 操作网络数据_第18张图片

https://igraph.org/r/
存储在图的形式——邻接列表
https://visualgo.net/zh/graphds
https://gk.palem.in/iGraphExport.html
https://www.cnblogs.com/alan-blog-TsingHua/p/10924894.html

你可能感兴趣的:(网络数据统计分析笔记|| 操作网络数据)