前言
接下去的部分,我们要开始介绍层次关系与网络关系图片的绘制。
层次关系型图标主要用于表达个体之间的层次关系,通常可以用来展示分类的多级关系,例如层次聚类的树状图、节点连接图、冰柱图、旭日图、圆填充图、矩形树状图等
不同于层次关系结构,网络关系结构并不是自底向上或自顶向下的层次结构,展示了不同元素之间的更加自由和复杂的相互关系。如桑葚图、和弦图、弧长链接图、蜂箱图、边绑定图等。
在图论中,图是由若干个节点或顶点(node
或 vertex
)和连接两个节点的边(edge
)构成的图形,用于表示事物之间的关系,而树也是图的一种。
在生物信息领域,最常见的网络图应该就是基因/蛋白质互作网络图,例如常见的 KEGG
通路图,而 GO
通路则是以树的形式展现各生物学过程之间的包含、并列关系。
在 R
中,绘制这些图形的包也比较多,如 igraph
、ggraph
、circlize
。而我们也主要介绍这三个包。
在开始绘制这些图形之前,我们先从介绍包的使用开始。首先是 igraph
igraph
igraph
是一个集成的高效且易于使用的网络分析工具,可以在 R
、Python
、C/C++
和 Mathematica
中使用。
安装导入
install.packages("igraph")
library(igraph)
创建图形
1. 创建简单图形
使用 graph
或 make_graph
函数可以创建一个简单的有向图
g <- graph(edges = c(1, 2, 2, 3, 3, 4, 5, 6))
# g <- make_graph(edges = c(1, 2, 2, 3, 3, 4, 5, 6))
我们为 edges
参数传递了一个边向量,其中第一、二两个元素构成一条边,第三、四两个元素构成一条边,以此类推。
如果传递的是数值向量,会将值作为节点的 ID
,字符向量的值将作为节点的名称,函数返回一个 igraph
对象
> class(g)
[1] "igraph"
直接将返回的 igraph
对象传递给 plot
函数,就可以显示图形
plot(g)
默认绘制的是有向图,可以设置 directed = FALSE
绘制无向图
g <- graph(edges = c("A", "B", "B", "C", "C", "D"), directed = FALSE)
plot(g)
也可以使用对应的简便函数来绘制有向图和无向图
directed_graph(...)
undirected_graph(...)
# 相当于
make_directed_graph(edges, n = max(edges))
make_undirected_graph(edges, n = max(edges))
例如
g <- undirected_graph(edges = c("A", "B", "B", "C", "C", "D"))
plot(g)
也可以传递字符标量
graph <- graph(
~ A-B-C-D-A, E-A:B:C:D,
F-G-H-I-F, J-F:G:H:I,
K-L-M-N-K, O-K:L:M:N,
P-Q-R-S-P, T-P:Q:R:S,
B-F, E-J, C-I, L-T, O-T, M-S,
C-P, C-L, I-L, I-P)
plot(graph)
或者传入预定义的一些图形名称
solids <- list(
graph("Tetrahedron"),
graph("Cubical"),
graph("Octahedron"),
graph("Dodecahedron"),
graph("Icosahedron"),
graph("Bull"),
graph("Coxeter"),
graph("Diamond"),
graph("Levi")
)
par(mfrow=c(3,3))
for (i in seq_along(solids)) {
x = (i - 1) %/% 3 + 1
y = (i - 1) %% 3 + 1
plot(solids[[i]])
}
2. 创建特定图形
2.1 特定图形
igraph
还提供了许多 make_*
形式的函数,用于创建不同结构的图
例如,创建一个环形图
g <- make_ring(10)
星形图
make_star(10, mode = "out")
栅格图
g <- make_lattice(length = 5, dim = 2)
构建一棵二叉树
g <- make_tree(10, 2)
创建全连接图
g <- make_full_graph(5)
创建一个没有边的图
g <- make_empty_graph(10)
2.2 随机图形
igraph
中提供的 sample_*
函数,用于生成随机图形
伯努利随机图,n、m
分别代表节点和边的个数
g <- sample_gnm(n = 20, m = 20)
n、p
分别设置节点个数和每两个节点之间绘制边的概率
g <- sample_gnp(n = 20, p = 1/10)
3. graph_from_literal
graph_from_literal
可以方便的创建较小的图,以传递表达式的方式来创建图形。
表达式由节点名称和边运算符组成,-
表示无向的边, +
表示有向边。边可以是任意长度,即可以添加任意数量的 -
,如果只包含 -
,则创建无向图。
例如
graph_from_literal(A-B)
graph_from_literal( A-----B, C--D, E--F, G--H, I, J, K )
:
操作符用于定义节点集合,如果连接两个集合,则集合中的每个节点都会与另一个集合相连
graph_from_literal( A:B:C:D -- A:B:C:D )
添加箭头
graph_from_literal( A +-+ B +---+ C ++ D + E)
在有向图中,只有包含 +
的边才会绘制,例如
graph_from_literal( A +- B -- C )
如果节点的名称包含空格或其他特殊字符,需要添加引号
graph_from_literal( "my" +- "salary is " -+ "$100" )
4. 从数据中创建
4.1 使用数据框创建
可以使用 graph_from_data_frame
(或 from_data_frame
) 函数从一个或多个包含节点或边的数据框中创建 igraph
对象。
graph_from_data_frame(d, directed = TRUE, vertices = NULL)
from_data_frame(...)
根据 vertices
参数是否为 null
,会有两种不同的操作模式。
如果 vertices = NULL
,则数据框的前两列表示边列表,剩下的列表示边的属性。
如果 vertices
不为空,则必须是一个包含节点信息的数据框。第一列将作为节点的名称,显示在图中,其他列作为节点的属性,且只保留边列表 d
中包含这些节点的边
示例
# 定义节点
actors <- data.frame(
name = c("Alice", "Bob", "Cecil", "David",
"Esmeralda"),
age = c(48, 33, 45, 34, 21),
gender = c("F", "M", "F", "M", "F")
)
# 定义边
relations <- data.frame(
from = c("Bob", "Cecil", "Cecil", "David",
"David", "Esmeralda"),
to = c("Alice", "Bob", "Alice", "Alice", "Bob", "Alice"),
same.dept = c(FALSE, FALSE, TRUE, FALSE, FALSE, TRUE),
friendship = c(4, 5, 5, 2, 1, 1),
advice = c(4, 5, 5, 4, 2, 3)
)
# 将数据转换为 igraph 对象
g <- graph_from_data_frame(
relations, directed = TRUE,
vertices = actors
)
plot(g)
as_data_frame
用于将 igraph
对象转换为一个或多个数据框。根据 what
参数来进行转换,可选的值为 c("edges", "vertices", "both")
> as_data_frame(g, what = "edges")
from to same.dept friendship advice
1 Bob Alice FALSE 4 4
2 Cecil Bob FALSE 5 5
3 Cecil Alice TRUE 5 5
4 David Alice FALSE 2 4
5 David Bob FALSE 1 2
6 Esmeralda Alice TRUE 1 3
> as_data_frame(g, what = "vertices")
name age gender
Alice Alice 48 F
Bob Bob 33 M
Cecil Cecil 45 F
David David 34 M
Esmeralda Esmeralda 21 F
如果为 both
,则会将节点和边以数据框列表的形式返回
4.2 使用边列表
graph_from_edgelist
用于从边列表来创建 igraph
对象,接受一个包含两列的矩阵,每行定义了一条边。
el <- matrix( c("foo", "bar", "bar", "foobar"), nc = 2, byrow = TRUE)
g <- graph_from_edgelist(el)
创建一个环形图
g <- graph_from_edgelist(cbind(1:10, c(2:10, 1)))
4.3 邻接矩阵
graph_from_adjacency_matrix
是一个灵活的函数,能够使用邻接矩阵来创建 igraph
对象
graph_from_adjacency_matrix(adjmatrix, mode = c("directed", "undirected",
"max", "min", "upper", "lower", "plus"), weighted = NULL,
diag = TRUE, add.colnames = NULL, add.rownames = NA)
节点的顺序将依照矩阵的顺序排序,mode
参数各个值的含义为:
-
directed
:有向图 -
undirected
:无向图,与max
一样 -
max
:将max(A(i,j), A(j,i))
作为无向图边的值 -
upper
:使用上三角来构建无向图 -
lower
:使用下三角来构建无向图 -
min
:将min(A(i,j), A(j,i))
作为无向图边的值 -
plus
:将A(i,j)+A(j,i)
作为无向图边的值
如果 weighted
参数为 TRUE
,会创建加权图
示例
adjm <- matrix(sample(0:1, 100, replace = TRUE, prob = c(0.9, 0.1)), nc = 10)
g1 <- graph_from_adjacency_matrix(adjm)
plot(g1)
g2 <- graph_from_adjacency_matrix(adjm, weighted=TRUE)
获取 igraph
对象节点的权重
> E(g2)$weight
[1] 1 1 1 1 1 1 1 1 1
设置行列名称
colnames(adjm) <- sample(letters, ncol(adjm))
rownames(adjm) <- seq(nrow(adjm))
g3 <- graph_from_adjacency_matrix(adjm, weighted=TRUE, add.rownames="code")
plot(g3)
4.4 图层
我们还可以使用类似 ggplot2
图层的方式,使用 +
来添加节点和边,例如
g <- make_empty_graph(directed = FALSE) +
vertices(LETTERS[1:10]) +
edges('A','B', 'B','D', 'C','D', 'D','E', 'E','G', 'F','G', 'G','H', 'H','I', 'I','J')
plot(g)
我们首先使用 make_empty_graph
创建一个空的图,默认为有向图,设置 directed = FALSE
来绘制无向图
然后,使用 +
来添加 vertices()
创建的结点和 edges()
创建的边
还可以使用 -
来删除某些节点或者边,例如
g <- make_empty_graph(directed = FALSE) +
vertices(LETTERS[1:10]) +
edges('A','B', 'B','D', 'C','D', 'D','E', 'E','G', 'F','G', 'G','H', 'H','I', 'I','J') -
vertices(LETTERS[5]) -
edges('A|B', 'I|J')
plot(g)
删除边的使用,传递给 edges()
的值略有不同,要删除的边为使用 |
连接两个节点名称的字符串形式
网友评论