R 数据可视化 —— igraph 对象
igraph 对象
例如,我们有如下 igraph
对象
g <- graph(
edges = c('A', 'B', 'B','D',
'C','D', 'D','E',
'E','G', 'F','G',
'G','H', 'H','I',
'I','J')
)
![](https://img.haomeiwen.com/i18546936/b5423731f697938f.png)
查看对象
> g
IGRAPH 0e3645c DN-- 10 9 --
+ attr: name (v/c)
+ edges from 0e3645c (vertex names):
[1] A->B B->D C->D D->E E->G F->G G->H H->I I->J
在第一行中,16
进制数后面的字符分别代表:
-
D
或U
表示有向和无向 -
N
表示命名图,即节点有name
属性
还有两个字符
-
W
表示加权图,即边存在weight
属性 -
B
表示bipartite (two-mode) graph
,即节点存在type
属性
后面的两个数值 (10 9)
表示节点和边的数量
第二行为节点和边的属性,其中括号中的字符分别表示:
-
g
:graph
-
v
:vertex
-
e
:edge
-
n
:numeric
-
c
:character
-
l
:logical
-
x
:complex
例子中的 name
为节点的字符型属性
获取图的大小
# 获取图的顺序,即节点数
> gorder(g)
[1] 10
# 获取图的大小,即边的数量
> gsize(g)
[1] 9
提取子图
以传递节点 ID
的方式,获取指定节点及这些节点之间的边,构建子图
g2 <- induced_subgraph(g, 1:5)
![](https://img.haomeiwen.com/i18546936/b4e4c44073023386.png)
以指定边 ID
的方式,获取包含指定边及边所涉及到的节点,构建子图
g3 <- subgraph.edges(g, 1:5)
![](https://img.haomeiwen.com/i18546936/0419be41430da70b.png)
1. 查询
1.1 邻接矩阵
最直接的表示图的方法是邻接矩阵,行列与节点对应,如果两个节点之间存在连接,则矩阵中对应位置的值为 1
,否则为 0
。对于加权图来说,值代表的是边的权重。
对于无向图来说,邻接矩阵总是对称的,而对于有向图来说并不一定是对称的。
使用 []
可以返回对象的邻接矩阵,也可以使用 get.adjacency(g)
来获取
> g[]
10 x 10 sparse Matrix of class "dgCMatrix"
[[ suppressing 10 column names ‘A’, ‘B’, ‘D’ ... ]]
A . 1 . . . . . . . .
B . . 1 . . . . . . .
D . . . . 1 . . . . .
C . . 1 . . . . . . .
E . . . . . 1 . . . .
G . . . . . . . 1 . .
F . . . . . 1 . . . .
H . . . . . . . . 1 .
I . . . . . . . . . 1
J . . . . . . . . . .
返回的是一个稀疏矩阵
获取对应的边
> g['A', 'F']
[1] 0
0
表示不存在 A
到 F
的边,我们可以将其设置为 1
,意味着会添加这条边
> g['A', 'F'] <- 1
> g['A', 'F']
[1] 1
![](https://img.haomeiwen.com/i18546936/9dfb8c4a82afda67.png)
如果要删除一条边,可以将邻接矩阵对应位置的值设置为 0
,例如
g['D', 'E'] <- 0
![](https://img.haomeiwen.com/i18546936/5948037e81051d80.png)
查询多条边会返回一个矩阵
> g[c('A', 'B', 'C'),c('A', 'B', 'C', 'D')]
3 x 4 sparse Matrix of class "dgCMatrix"
A B C D
A . 1 . .
B . . . 1
C . . . 1
获取一个节点与其他所有节点之间的连接
> g['A',]
A B D C E G F H I J
0 1 0 0 0 0 1 0 0 0
> g[,'G']
A B D C E G F H I J
0 0 0 0 1 0 1 0 0 0
以数字索引的方式
> g[2,]
A B D C E G F H I J
0 0 1 0 0 0 0 0 0 0
> g[2,-1]
B D C E G F H I J
0 1 0 0 0 0 0 0 0
条件查询
> degree(g)
A B D C E G F H I J
2 2 2 1 1 3 2 2 2 1
> g[degree(g) > 2, degree(g) < 3]
A B D C E F H I J
0 0 0 0 0 0 1 0 0
配对节点
> g[from = c('A', 'B', 'C'), to = c('C', 'D', 'E')]
[1] 0 1 0
将会查询的边为 A-C
、B-D
、C-E
,需要保证 from
和 to
的长度一致
获取邻接节点
> neighbors(g, 'G')
+ 1/10 vertex, named, from e70593c:
[1] H
1.2 邻接表
邻接表是以表的形式来表示图的,只存储每个节点中与其相连的节点
> g[[]]
$A
+ 2/10 vertices, named, from e70593c:
[1] B F
$B
+ 1/10 vertex, named, from e70593c:
[1] D
...
$I
+ 1/10 vertex, named, from e70593c:
[1] J
$J
+ 0/10 vertices, named, from e70593c:
获取节点的邻接节点
> g[[c('A', 'B')]]
$A
+ 2/10 vertices, named, from e70593c:
[1] B F
$B
+ 1/10 vertex, named, from e70593c:
[1] D
不同方向的邻接节点
> g[['G', ]]
$G
+ 1/10 vertex, named, from e70593c:
[1] H
> g[[, 'G']]
$G
+ 2/10 vertices, named, from e70593c:
[1] E F
显示边
> g[['A', edges = TRUE]]
$A
+ 2/9 edges from e70593c (vertex names):
[1] A->B A->F
获取两个节点集合之间的边
> g[[c('A', 'B', 'C'),c('C', 'D', 'E', 'F'), edges = TRUE]]
[[1]]
+ 1/9 edge from e70593c (vertex names):
[1] A->F
[[2]]
+ 1/9 edge from e70593c (vertex names):
[1] B->D
[[3]]
+ 1/9 edge from e70593c (vertex names):
[1] C->D
2. 节点和边
使用 E()
和 V()
函数,可以获取 igraph
对象的边和节点。例如
> E(g)
+ 9/9 edges from 063a143 (vertex names):
[1] A->B B->D C->D D->E E->G F->G G->H H->I I->J
> V(g)
+ 10/10 vertices, named, from 063a143:
[1] A B D C E G F H I J
V()
的返回值是根据结点的 ID
进行了排序。由于我们的节点是字符型的,会根据节点添加的顺序自动为节点设置 ID
,第一个节点的 ID
为 1
可以使用两个节点名称之间添加一个竖线组成的字符串来引用连接两个节点的边,如果是无向图,则两个节点的顺序不影响边的引用
使用 ends()
可以获取边的矩阵表示
> g %>% ends('A|B')
[,1] [,2]
[1,] "A" "B"
>
> g %>% ends(E(g))
[,1] [,2]
[1,] "A" "B"
[2,] "B" "D"
[3,] "C" "D"
[4,] "D" "E"
[5,] "E" "G"
[6,] "F" "G"
[7,] "G" "H"
[8,] "H" "I"
[9,] "I" "J"
对于有向图,head_of
和 tail_of
可以获取边的头尾两个端点,有箭头的一端为头
> g %>% tail_of('A|B')
+ 1/10 vertex, named, from 063a143:
[1] A
> g %>% head_of('A|B')
+ 1/10 vertex, named, from 063a143:
[1] B
使用 neighbors
来获取节点的邻接节点
> g %>% neighbors('D', mode = "in")
+ 2/10 vertices, named, from 063a143:
[1] B C
> g %>% neighbors('D', mode = "out")
+ 1/10 vertex, named, from 063a143:
[1] E
对于无向图,两种模式的邻接节点是一样的
计算边和节点的数量
> ecount(g)
[1] 9
> vcount(g)
[1] 10
2.1 序列操作
节点序列操作
> V(g)[1:4]
+ 4/10 vertices, named, from 1ee19c4:
[1] A B D C
> V(g)[1:3, 5:7]
+ 6/10 vertices, named, from 1ee19c4:
[1] A B D E G F
> V(g)[c('A', 'C', 'D', 'G')]
+ 4/10 vertices, named, from 1ee19c4:
[1] A C D G
根据邻接节点索引
> V(g)[nei('D')]
+ 3/10 vertices, named, from 1ee19c4:
[1] B C E
> V(g)[innei('D')]
+ 2/10 vertices, named, from 1ee19c4:
[1] B C
> V(g)[outnei('D')]
+ 1/10 vertex, named, from 1ee19c4:
[1] E
查询条件
> V(g)[degree(g) > 2]
+ 2/10 vertices, named, from 1ee19c4:
[1] D G
反转、去重和集合操作
> rev(V(g))
+ 10/10 vertices, named, from 1ee19c4:
[1] J I H F G E C D B A
> unique(V(g)['A', 'A'])
+ 1/10 vertex, named, from 1ee19c4:
[1] A
> union(V(g)[1:3], V(g)[6:8])
+ 6/10 vertices, named, from 1ee19c4:
[1] A B D G F H
> intersection(V(g)[1:5], V(g)[4:8])
+ 2/10 vertices, named, from 1ee19c4:
[1] C E
> difference(V(g), V(g)[1:5])
+ 5/10 vertices, named, from 1ee19c4:
[1] G F H I J
获取边涉及的结点
> V(g)[inc('A|B'), inc('D|E')]
+ 4/10 vertices, named, from 1ee19c4:
[1] A B D E
边序列操作与节点类似
> E(g)[1:4]
+ 4/9 edges from 1ee19c4 (vertex names):
[1] A->B B->D C->D D->E
> E(g)[c('A|B', 'G|H', 'H|I')]
+ 3/9 edges from 1ee19c4 (vertex names):
[1] A->B G->H H->I
获取涉及到节点的边
> E(g)[inc('D')]
+ 3/9 edges from 1ee19c4 (vertex names):
[1] B->D C->D D->E
> E(g)[from('D')]
+ 1/9 edge from 1ee19c4 (vertex names):
[1] D->E
> E(g)[to('D')]
+ 2/9 edges from 1ee19c4 (vertex names):
[1] B->D C->D
条件索引
> E(g)[seq_len(gsize(g)) %% 2]
+ 5/9 edges from 1ee19c4 (vertex names):
[1] A->B A->B A->B A->B A->B
获取两个节点集合之间存在的边
# 不管方向
> E(g)[V(g)['D'] %--% V(g)['B', 'C', 'E']]
+ 3/9 edges from 1ee19c4 (vertex names):
[1] B->D C->D D->E
# 左到右
> E(g)[V(g)['D'] %->% V(g)['B', 'C', 'E']]
+ 1/9 edge from 1ee19c4 (vertex names):
[1] D->E
# 右到左
> E(g)[V(g)['D'] %<-% V(g)['B', 'C', 'E']]
+ 2/9 edges from 1ee19c4 (vertex names):
[1] B->D C->D
集合操作、去重和反转和节点操作一样
注意:我们在中括号中使用的简写函数只能在对应条件下使用,无法单独使用
> nei(g, 'A')
Error in nei(g, "A") : 没有"nei"这个函数
> from('A')
Error in from("A") : 没有"from"这个函数
3. 元数据属性
我们可以将节点和边的元数据(附加信息)作为属性值的方式添加到节点和边的属性中
使用 $
可以获取和设置属性,例如,获取节点的 name
属性
> V(g)$name
[1] "A" "B" "D" "C" "E" "G" "F" "H" "I" "J"
为节点新建一个名为 class
的属性
> V(g)$class <- rep(c("I", "II"), each = 5)
> neighbors(g, 'G', mode = "all")$class
[1] "I" "II" "II"
为边设置属性值
> E(g)$type <- rep(c('activation', 'repression', 'inhibition'), each = 3)
> E(g)$weight <- sample(3:6, 9, replace = TRUE)
也可以使用 set_edge_attr
和 set_vertex_attr
函数来设置,效果是一样的
获取所有节点和边的属性
> edge_attr(g)
$type
[1] "activation" "activation" "activation" "repression" "repression" "repression" "inhibition" "inhibition"
[9] "inhibition"
$weight
[1] 3 4 3 3 6 4 3 5 6
> vertex_attr(g)
$name
[1] "A" "B" "D" "C" "E" "G" "F" "H" "I" "J"
$class
[1] "I" "I" "I" "I" "I" "II" "II" "II" "II" "II"
可以使用 delete_edge_attr
和 delete_vertex_attr
删除属性
获取图属性
> g$name
[1] "demo"
> graph_attr(g)
$name
[1] "demo"
> graph_attr_names(g)
[1] "name"
> graph_attr(g, 'name')
[1] "demo"
设置图的属性
g$name <- "demo"
# or
g <- set_graph_attr(g, 'name', 'demo')
删除图属性
> g <- set_graph_attr(g, 'some', 'something')
> graph_attr(g)
$name
[1] "demo"
$some
[1] "something"
> g <- delete_graph_attr(g, 'some')
> graph_attr(g)
$name
[1] "demo"
上面的属性设置都是在已经构建完图之后,我们也可以在构建图的时候添加属性。例如
g <- make_empty_graph(n = 5) %>%
add_edges(c(1,2, 2,3, 3,4, 4,5)) %>%
set_edge_attr("color", value = "red") %>%
add_edges(c(5,1), color = "green") %>%
set_vertex_attr("color", value = "orange") %>%
add_vertices(3, color = "red") %>%
add_vertices(2, color = "green")
plot(g)
![](https://img.haomeiwen.com/i18546936/81eba368ae0c3774.png)
在这里,我们使用 add_edges
和 add_vertices
函数来添加边和节点,对应的,可以使用 delete_edges
和 delete_vertices
来删除边和节点
有几个特殊的属性:
![](https://img.haomeiwen.com/i18546936/73e717b071fc42e7.png)