龙空技术网

R 数据可视化——ggraph 图形创建与布局

烟火少年时 193

前言:

而今咱们对“用igraph做network图”大体比较关注,朋友们都想要学习一些“用igraph做network图”的相关知识。那么小编同时在网上收集了一些对于“用igraph做network图””的相关内容,希望兄弟们能喜欢,你们快快来了解一下吧!

前言

在前面几节,我们对 igraph 进行了一些简单介绍。接下来我们要介绍的是 ggraph 包的使用

通常,ggraph 会和 tidygraph 一起搭配使用,这两个包都是 Thomas Lin Pedersen 写的。

tidygraph 提供了一系列 tidy API 用于操作图,通常可以将图对象设计为两个 tidy 表,一个用于表示 node 数据,另一个用于表示 edge 数据。还提供了一些额外的动词用于操作这两个表,同时也提供了很多的图论算法,让图形对象的处理看起来更像是在处理数据框。

ggraphggplot2 的扩展,用于绘制关系型数据结构,如网络、图和树等。ggraph 包含 3 个核心概念:

layout:定义图的布局,包含所有的 igraph 布局以及额外的一些布局,如蜂巢图、圆堆积图等nodes:定义节点图形属性,使用 geom_node_*() 函数来控制edges:定义边的图形属性,使用 geom_edge_*() 函数来控制

两个包搭配使用,可以让网络对象的处理与绘制,和我们绘制数据框结构更相似,以 ggplot2 的方式来绘制网络对象

安装导入

install.packages('ggraph')install.packages('tidygraph')# 开发版devtools::install_github('thomasp85/ggraph')devtools::install_github('thomasp85/tidygraph')library(ggraph)library(tidygraph)
创建图

我们还是以 KEGG 的通路作为示例,这次我们找的是 p53 signaling pathway,网络结构的获取方式见前两节的代码

我们使用 tbl_graph() 函数来创建 tbl_graph 对象

edges <- read.csv('~/Downloads/p53_signaling_pathway.csv')colnames(edges) <- c("from", "to")nodes <- data.frame(name = unique(union(edges$from, edges$to)))g <- tbl_graph(nodes = nodes, edges = edges)

查看对象类型

> class(g)[1] "tbl_graph" "igraph" 

tbl_graph 对象本质上是一个 igraph 对象,可以看到 tbl_graph() 函数与 graph_from_data_frame() 函数的参数是很像的

也可以用 igraph 图对象来创建 tbl_graph 对象

library(igraph)ig <- graph_from_data_frame(d = edges, vertices = nodes)ig_tidy <- as_tbl_graph(ig)

查看这三个对象的类型

> class(g)[1] "tbl_graph" "igraph"   > class(ig)[1] "igraph"> class(ig_tidy)[1] "tbl_graph" "igraph">> is.tbl_graph(g)[1] TRUE> is.tbl_graph(ig)[1] FALSE> is.tbl_graph(ig_tidy)[1] TRUE

查看 tbl_graph 对象

> g# A tbl_graph: 61 nodes and 68 edges## A directed acyclic simple graph with 1 component## Node Data: 61 x 1 (active)  name    <chr> 1 MDM4  2 CHEK1 3 ATR   4 CHEK2 5 ATM   6 IGFBP3# … with 55 more rows## Edge Data: 68 x 2   from    to  <int> <int>1     1    222     1    153     2    15# … with 65 more rows

as_tbl_graph() 函数还可以将很多其他类型的数据转换为 tbl_graph 对象,例如 hclust 对象、邻接矩阵、dendrogram 对象等等

tidygraph 也提供了很多简便函数,create_*() 函数用于创建一些常见的图结构

par(mfrow= c(1, 3))plot(create_star(10))plot(create_ring(10))plot(create_tree(n = 20, children = 3), edge.arrow.size = .4)

play_*() 函数用于创建模拟图

par(mfrow= c(1, 3))plot(play_geometry(6, 1, torus = FALSE))plot(play_islands(4, 10, 0.7, 3))plot(play_forestfire(20, 0.5), edge.arrow.size = .2)

可以使用 igraph 的绘制方式来调整和绘制 tbl_graph 图对象

布局

使用 ggraph 来绘制图形

ggraph(g) +  geom_edge_link() +  geom_node_point() +  theme_graph()

ggraph() 函数相当于 ggplot2::ggplot(),根据传入的图对象以及布局来创建绘图对象

ggraph 默认会根据图结构自动推断布局,也可以使用指定 layout 参数的值

ggraph(g, layout = 'kk') +  geom_edge_link() +  geom_node_point() +  theme_graph()

如果布局算法可以接受额外的参数,也可以在 ggraph() 函数中一并指定

ggraph(g, layout = 'kk', maxiter = 100) +  geom_edge_link() +  geom_node_point() +  theme_graph()

或者用 create_layout() 函数来创建布局,它接受的参数与 ggraph() 一样,但是返回的是 layout_ggraph 对象,可以在后续的图结构中使用。例如

layout <- create_layout(g, layout = 'eigen')ggraph(layout) +  geom_edge_link() +  geom_node_point() +  theme_graph()

我们可以看到,返回的对象是包含节点位置及属性信息的数据框

> head(layout)            x          y circular   name .ggraph.orig_index .ggraph.index1 -0.04065655 0.05622353    FALSE   MDM4                  1             12 -0.01929743 0.04913762    FALSE  CHEK1                  2             23 -0.01929743 0.04913762    FALSE    ATR                  3             34 -0.01929743 0.04913762    FALSE  CHEK2                  4             45 -0.01929743 0.04913762    FALSE    ATM                  5             56  0.50281399 0.07229403    FALSE IGFBP3                  6             6

查看对象的所有属性

> attributes(layout)$names[1] "x"                  "y"                  "circular"           "name"               ".ggraph.orig_index"[6] ".ggraph.index"     $row.names [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39[40] 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61$class[1] "layout_tbl_graph" "layout_ggraph"    "data.frame"      $graph# A tbl_graph: 61 nodes and 68 edges## A directed acyclic simple graph with 1 component## Node Data: 61 x 2 (active)  name   .ggraph.orig_index  <chr>               <int>1 MDM4                    12 CHEK1                   23 ATR                     34 CHEK2                   45 ATM                     56 IGFBP3                  6# … with 55 more rows## Edge Data: 68 x 2   from    to  <int> <int>1     1    222     1    153     2    15# … with 65 more rows$circular[1] FALSE

ggraph 包提供了许多不同的布局,包括 igraph 所有的布局,同时也提供了一些它自己设计的布局,有超过 20 种布局可供选择。

通常来说,不同的布局算法对图的展示差异很大,因此,为自己的数据找到一个合适的布局很重要。

也可以自己设计一个布局函数,接受一个 tbl_graph 对象,并返回一个位置数据框。或者直接提供一个位置矩阵或数据框作为布局

1. 圆形布局

一些布局既可以显示在笛卡尔坐标系中,也可以在极坐标中有效地进行展示。对于 ggplot2 来说,可以使用 coord_polar() 转换为极坐标轴。但这并不适用于 ggraph,我们通过 circular 参数将布局转换为径向表示。

我们先为边添加一列信息,用于表示基因之间的表达值的相关性,-1 表示负相关,1 为正相关,0 为不相关

edges <- edges %>%  mutate(corr = sample(-1:1, size = n(), replace = TRUE))  g <- tbl_graph(nodes = nodes, edges = edges)
linear 布局

对于线性布局,即将所有基因放置在一条直线上,然后使用 geom_edge_arc 将边绘制成弧形

ggraph(g, layout = 'linear') +   geom_edge_arc(aes(colour = factor(corr))) +  geom_node_point() +  theme_graph()

设置 circular = TRUE,转换为径向表示

ggraph(g, layout = 'linear', circular = TRUE) +   geom_edge_arc(aes(colour = factor(corr))) +  geom_node_point() +  coord_fixed() +  theme_graph()
partition 布局

分区布局是一种显示分层结构的方式,每一层都会对前一层的切片进行分割。

例如,我们将节点的形状设置为条块 geom_node_tile

graph <- tbl_graph(flare$vertices, flare$edges)ggraph(graph, 'partition') +   geom_node_tile(aes(fill = depth), size = 0.25) +  theme_graph()

分区布局的圆形表示,注意节点的形状变成了圆弧条形 geom_node_arc_bar

ggraph(graph, 'partition', circular = TRUE) +   geom_node_arc_bar(aes(fill = depth), size = 0.25) +  coord_fixed() +  theme_graph()

并不是所有的布局都支持圆形表示,下面的布局将会忽略 circular 参数

2. node — edge 布局

我们可以直接使用 igraph 中定义的布局算法,例如

lay <- c('stress', 'fr', 'lgl', 'graphopt')plot_fun <- function(g, layout) {  p <- ggraph(g, layout = layout) +     geom_edge_link(aes(colour = factor(corr)), show.legend = FALSE) +    geom_node_point() +     labs(caption = paste0('Layout: ', layout)) +    theme_graph()  return(p)}grid.newpage()pushViewport(viewport(layout = grid.layout(2, 2)))for (i in seq_along(lay)) {  x = (i - 1) %/% 2 + 1  y = (i - 1) %% 2 + 1  p = plot_fun(g, lay[i])  print(p, vp = viewport(layout.pos.row = x, layout.pos.col = y))}
3. 蜂巢图

蜂巢图也是一种 node-edge 图,它使用的是节点的信息,将节点进行分类

g <- g %>%  mutate(friends = ifelse(    centrality_degree(mode = 'all') < 3, "few",    ifelse(centrality_degree(mode = 'all') > 3, "many", "medium")  ))ggraph(g, 'hive', axis = friends) +   geom_edge_hive(aes(colour = factor(corr))) +   geom_axis_hive(aes(colour = friends), size = 2, label = FALSE) +   coord_fixed() +  theme_graph()
4. 焦点布局

将焦点聚集在一个或一组节点上,其他节点则相对于该位置放置

ggraph(g, 'focus', focus = node_is_center()) +   ggforce::geom_circle(aes(x0 = 0, y0 = 0, r = r), data.frame(r = 1:5), colour = 'grey') +  geom_edge_link(aes(colour = factor(corr)), show.legend = FALSE) +   geom_node_point() +   coord_fixed() +  theme_graph()
5. 层次布局圆堆积图:以包含的方式来展示层次结构
graph <- tbl_graph(flare$vertices, flare$edges)ggraph(graph, 'circlepack', weight = size) +   geom_node_circle(aes(fill = factor(depth)), size = 0.25, n = 50) +   coord_fixed() +  theme_graph()
堆积树状图
ggraph(graph, 'circlepack', weight = size) +   geom_edge_link() +   geom_node_point(aes(colour = factor(depth))) +  coord_fixed() +  theme_graph()
树状图

矩形层次关系

ggraph(graph, 'treemap', weight = size) +   geom_node_tile(aes(fill = factor(depth)), size = 0.25) +  theme_graph()
ggraph(graph, 'treemap', weight = size) +   geom_edge_link() +   geom_node_point(aes(colour = factor(depth))) +  theme_graph()

根据树的不同深度进行绘制

ggraph(graph, 'tree') +   geom_edge_diagonal() +  theme_graph()

层次聚类树状图

dendrogram <- hclust(dist(iris[, 1:4]))ggraph(dendrogram, 'dendrogram', height = height) +   geom_edge_elbow() +  theme_graph()

圆形树状图

ggraph(dendrogram, 'dendrogram', circular = TRUE) +   geom_edge_elbow() +   coord_fixed() +  theme_graph()

系统发育树,不存在根节点,使用无根布局

tree <- create_tree(100, 2, directed = FALSE) %>%   activate(edges) %>%   mutate(length = runif(n()))ggraph(tree, 'unrooted', length = length) +   geom_edge_link() +  theme_graph()
6. 矩阵布局

矩阵布局是将节点放置在对角线,如果对应位置的两个节点之间有交叠,那矩阵中对应的行列将会绘制一个点或矩形。

graph <- create_notable('zachary')ggraph(graph, 'matrix', sort.by = node_rank_leafsort()) +   geom_edge_point(mirror = TRUE) +   coord_fixed() +  theme_graph()

不同的节点顺序,会影响矩阵布局的形状

ggraph(graph, 'matrix', sort.by = node_rank_spectral()) +   geom_edge_point(mirror = TRUE) +   coord_fixed() +  theme_graph()
7. Fabric 布局

Fabric 布局是一种可扩展的特殊的 BioFabric 布局。其特殊的地方在于,它将节点表示为水平线,边表示为连接两个水平线的竖直线

ggraph(g, 'fabric', sort.by = node_rank_fabric()) +   geom_node_range(colour = 'grey') +   geom_edge_span(end_shape = 'square') +   coord_fixed() +  theme_graph()

添加一份重复的阴影边

ggraph(g, 'fabric', sort.by = node_rank_fabric(), shadow.edges =TRUE) +   geom_node_range(colour = 'grey') +   geom_edge_span(aes(filter = shadow_edge), colour ='lightblue' , end_shape = 'square') +   geom_edge_span(aes(filter = !shadow_edge), end_shape = 'square') +   coord_fixed() +  theme_graph()

标签: #用igraph做network图