R ggplotR语言生物信息

R 数据可视化 —— igraph 函数应用

2021-05-24  本文已影响0人  名本无名

前言

igraph 提供了许多图论算法,例如我们熟知的最短路径、最大流最小割、最小生成树等。

我们针对下面的图,介绍一些简单的图论相关的函数

g <- graph_from_data_frame(d = sub_path, vertices = node_attr)

V(g)$color <- if_else(V(g)$type == "other", "#80b1d3", "#fb8072")
V(g)$size <- (V(g)$mut_class + 1) * 6

E(g)$weight <- abs(rnorm(n = ecount(g)))
E(g)$arrow.size <- .2
E(g)$edge.color <- "gray80"
graph_attr(g, "layout") <- layout_with_lgl
plot(g)

1. 距离和路径

计算平均路径长度,即每对基因之间的最短距离的均值

> mean_distance(g)
[1] 2.625

当图是无向图时的平均路径长度

> mean_distance(g, directed = FALSE)
[1] 2.571429

计算所有位点之间的最短路径,默认会考虑边的权重

> distances(g, weights = NA)
       EGFR SOS1 SOS2 GRB2 EGF MAP2K1 MAP2K2 ARAF RAF1 BRAF HRAS KRAS NRAS MAPK1 MAPK3
EGFR      0    2    2    1   1      5      5    4    4    4    3    3    3     6     6
SOS1      2    0    2    1   3      3      3    2    2    2    1    1    1     4     4
SOS2      2    2    0    1   3      3      3    2    2    2    1    1    1     4     4
GRB2      1    1    1    0   2      4      4    3    3    3    2    2    2     5     5
EGF       1    3    3    2   0      6      6    5    5    5    4    4    4     7     7
MAP2K1    5    3    3    4   6      0      2    1    1    1    2    2    2     1     1
MAP2K2    5    3    3    4   6      2      0    1    1    1    2    2    2     1     1
ARAF      4    2    2    3   5      1      1    0    2    2    1    1    1     2     2
RAF1      4    2    2    3   5      1      1    2    0    2    1    1    1     2     2
BRAF      4    2    2    3   5      1      1    2    2    0    1    1    1     2     2
HRAS      3    1    1    2   4      2      2    1    1    1    0    2    2     3     3
KRAS      3    1    1    2   4      2      2    1    1    1    2    0    2     3     3
NRAS      3    1    1    2   4      2      2    1    1    1    2    2    0     3     3
MAPK1     6    4    4    5   7      1      1    2    2    2    3    3    3     0     2
MAPK3     6    4    4    5   7      1      1    2    2    2    3    3    3     2     0

设置 weights = NA,表示不考虑边的权重

使用 distances,我们可以计算我们感兴趣的基因与其他基因之间的距离,例如,我们想知道 EGFR 与其他基因之间的距离

dist_egfr <- distances(g, v = V(g)[1], to = V(g), weights = NA)
# 设置颜色板
pal <- colorRampPalette(c("#fb8072", "#80b1d3"))
col <- pal(max(dist_egfr) + 1)

plot(g, vertex.color = col[dist_egfr+1], vertex.label = dist_egfr,
     edge.arrow.size = .4, vertex.label.color = "white")

我们也可以只计算某两个基因之间的最短路径,例如,计算 EGFRMAPK1 之间的最短距离

e2m_path <- shortest_paths(g, from = V(g)[name == "EGFR"],
               to = V(g)[name == "MAPK1"],
               output = "both")
# 设置边的颜色
edge_col <- rep("grey80", ecount(g))
edge_col[unlist(e2m_path$epath)] <- "#80b1d3"
# 设置边的宽度
edge_width <- rep(2, ecount(g))
edge_width[unlist(e2m_path$epath)] <- 4
# 设置节点的颜色
vcol <- rep("gray40", vcount(g))
vcol[unlist(e2m_path$vpath)] <- "#fb8072"

plot(g, vertex.color=vcol, edge.color=edge_col, 
     edge.width=edge_width, edge.arrow.size = .6,
     vertex.label.cex = 1
     )

我们可以获取与一个基因相关的所有边,例如

> incident(g,  V(g)[name=="KRAS"], mode="in")
+ 2/29 edges from d01cfa6 (vertex names):
[1] SOS1->KRAS SOS2->KRAS
> incident(g,  V(g)[name=="KRAS"], mode="out")
+ 3/29 edges from d01cfa6 (vertex names):
[1] KRAS->ARAF KRAS->RAF1 KRAS->BRAF

也可以一次性获取多个基因的边

> incident_edges(g, V(g)[1:2], mode = "all")
$EGFR
+ 2/29 edges from d01cfa6 (vertex names):
[1] EGFR->GRB2 EGF ->EGFR

$SOS1
+ 4/29 edges from d01cfa6 (vertex names):
[1] SOS1->HRAS SOS1->KRAS SOS1->NRAS GRB2->SOS1

类似地,我们可以获取与一个基因直接互作的基因

> neighbors(g, V(g)[name == "KRAS"], mode = "all")
+ 5/15 vertices, named, from d01cfa6:
[1] SOS1 SOS2 ARAF RAF1 BRAF

获取调控 KRAS 基因的基因

> neighbors(g, V(g)[name == "KRAS"], mode = "in")
+ 2/15 vertices, named, from d01cfa6:
[1] SOS1 SOS2

获取被 KRAS 调控的基因

> neighbors(g, V(g)[name == "KRAS"], mode = "out")
+ 3/15 vertices, named, from d01cfa6:
[1] ARAF RAF1 BRAF

如果我们想获取多个感兴趣的基因的直接互作基因,可以使用 adjacent_vertices()

> adjacent_vertices(g, v = V(g)[c(1, 5)], mode = "all")
$EGFR
+ 2/15 vertices, named, from d01cfa6:
[1] GRB2 EGF 

$EGF
+ 1/15 vertex, named, from d01cfa6:
[1] EGFR

上面两个函数获取的都是直接互作的基因,即一步互作基因。如果想要获取多步互作基因,可以使用 ego() 函数,并设置 order 参数。

> ego(g, order = 1, nodes = V(g)["KRAS"])
[[1]]
+ 6/15 vertices, named, from d01cfa6:
[1] KRAS SOS1 SOS2 ARAF RAF1 BRAF
> ego(g, order = 2, nodes = V(g)["KRAS"])
[[1]]
+ 11/15 vertices, named, from d01cfa6:
 [1] KRAS   SOS1   SOS2   ARAF   RAF1   BRAF   GRB2   HRAS   NRAS   MAP2K1 MAP2K2

order = 2 或包含 order = 0order = 1 的结果

# 获取 KRAS 的所有边
inc.edge <- incident(g,  V(g)[name=="KRAS"], mode="all")
# 设置这些边的颜色
ecol <- rep("grey80", ecount(g))
ecol[inc.edge] <- "#33a02c"

# 获取直接互作基因
nei.node <- neighbors(g, V(g)[name == "KRAS"], mode = "all")
# 设置这些基因的颜色
vcol <- rep("gray40", vcount(g))
vcol[nei.node] <- "#fb8072"
vcol[V(g)[name == "KRAS"]] <- "#80b1d3"

plot(g, vertex.color=vcol, edge.color=ecol)

2. 连通性

判断一个图是不是连通的、是强连通图还是弱连通图,可以使用 is_connected

> is_connected(g)
[1] TRUE
> is_connected(g, mode = "weak")
[1] TRUE
> is_connected(g, mode = "strong")
[1] FALSE

可以使用 count_components 计算连通分量的数目

> count_components(g)
[1] 1

因为我们的图是连通的,所以只有一个连通分量

获取图中的连通分量信息

> components(g)
$membership
  EGFR   SOS1   SOS2   GRB2    EGF MAP2K1 MAP2K2   ARAF   RAF1   BRAF   HRAS   KRAS   NRAS  MAPK1  MAPK3 
     1      1      1      1      1      1      1      1      1      1      1      1      1      1      1 

$csize
[1] 15

$no
[1] 1

是不是有向非循环图(DAG

> is_dag(g)
[1] TRUE

对于如下图

g1 <- sample_gnp(20, 1/20)
plot(g1)
> count_components(g1)
[1] 12
> is_connected(g1)
[1] FALSE

将图分解为连通分量列表

> decompose(g1)
[[1]]
IGRAPH dd688c4 U--- 3 2 -- Erdos renyi (gnp) graph
+ attr: name (g/c), type (g/c), loops (g/l), p (g/n)
+ edges from dd688c4:
[1] 1--2 1--3
...
[[12]]
IGRAPH 7f3046a U--- 1 0 -- Erdos renyi (gnp) graph
+ attr: name (g/c), type (g/c), loops (g/l), p (g/n)
+ edges from 7f3046a:

根据连通分量进行分组

igraph::groups(components(g1))
$`1`
[1] 1 8 9
...
$`4`
[1]  4  6 12 13 17 19
...
$`12`
[1] 20

找到所有与给定顶点连通的点

> subcomponent(g1, 1)
+ 3/20 vertices, from 360a2eb:
[1] 1 8 9
> subcomponent(g1, 4)
+ 6/20 vertices, from 360a2eb:
[1]  4 13 17  6 12 19

3. 社区检测

有一些算法用于检测一些群组,即在群组内密集连接的节点,而群组之间的连接较少。

  1. 基于 Newman-Girvan

通过不断地删除网络中的边来检测网络中的社区。在最终剩余的网络中的连通分量也就是社区

计算图的社区结构

ceb <- cluster_edge_betweenness(g)

绘制社区结构树状图

dendPlot(ceb, mode="hclust")

在图中展示社区结构

plot(ceb, g)

我们可以来看下社区检测对象

> class(ceb)
[1] "communities"

获取社区结构的数目

> length(ceb)
[1] 3

查看每个社区结构包含的成员

> membership(ceb) 
  EGFR   SOS1   SOS2   GRB2    EGF MAP2K1 MAP2K2   ARAF   RAF1   BRAF   HRAS   KRAS   NRAS  MAPK1  MAPK3 
     1      2      2      1      1      3      2      2      2      2      2      2      2      3      3 

分区的高度模块化反映了社区内的紧密连接和跨社区的稀疏连接。即基因之间的紧密互作关系。

  1. 基于贪婪算法

这个函数试图通过直接优化模块化得分来寻找密集子图

cfg <- cluster_fast_greedy(as.undirected(g))
plot(cfg, as.undirected(g))
  1. 基于随机游走

基于随机游走的思想,即短的随机游走往往停留在同一个社区

cw <- cluster_walktrap(g)
plot(cw, g)

还有其他的一些社区检测函数,例如 cluster_leading_eigencluster_label_propcluster_louvain 等,就不再一一介绍了

我们也可以自定义设置每个社区的绘制,例如

V(g)$community <- cfg$membership
col <- c("#fb8072", "#80b1d3", "#fdb462", "#b3de69")

plot(g, vertex.color = col[V(g)$community])

4. 节点的度

degree 可以计算节点的度,其中 mode 参数的值可以是:

plot(g, vertex.size = degree(g, mode = "all") * 3)

查看节点度的分布

deg.dist <- degree_distribution(g, cumulative=T, mode="all")

plot(
  x = 0:max(deg),
  y = 1 - deg.dist,
  pch = 19, cex = 1.2,
  col = "orange", xlab = "Degree",
  ylab = "Cumulative Frequency"
)

5. 网页分析算法

PageRank 算法是 Google 使用的网页排名算法。其基本假设是,重要的页面往往会被很多其他页面引用,即指向该节点的节点越多,则该节点越重要。

我们可以将该算法应用于基因互作网络的分析,越多的基因来调控的某些基因可能行使的功能越重要

pg <- page_rank(g)$vector
plot(g, vertex.size=pg*400)

Hyperlink-Induced Topic Search(HITS) 算法也是一个网页排序算法,与 PageRank 不同的是,它将网页分为:

一个页面的 Authority 值和 Hub 值的计算公式为
$$
\begin{align}
auth(p) = \sum_{q \in p_{to}}{hub(q)}\

hub(p) = \sum_{q \in p_{from}}{auth(q)}
\end{align}
$$

hs <- hub_score(g, weights=NA)$vector
as <- authority_score(g, weights=NA)$vector

par(mfrow=c(1,2))

plot(g, vertex.size=hs*50, main="Hubs")
plot(g, vertex.size=as*30, main="Authorities")

6. 图形的集合操作

我们可以使用 %du% 操作符合并两张图

g1 <- make_star(10, mode="undirected")
V(g1)$name <- letters[1:10]
g2 <- make_ring(10)
V(g2)$name <- letters[6:15]
plot(g1 %du% g2)

使用 %u% 取两张图的并集

plot(g1 %u% g2)

可以看到,由于两张图之间有交叠的节点,最后会合并为一张图

使用 %m% 取两张图的差集

plot(g1 %m% g2)

使用 %d% 取两张图的交集

par(mfcol = c(1, 2))
net1 <- graph_from_literal(D-A:B:F:G, A-C-F-A, B-E-G-B, A-B, F-G,
                           H-F:G, H-I-J)
net2 <- graph_from_literal(D-A:F:Y, B-A-X-F-H-Z, F-Y)

plot(net1 %du% net2, main = "disjoint union")
plot(net1 %s% net2, main = "intersection")
上一篇下一篇

猜你喜欢

热点阅读