基于R语言绘制Network几种方式

平时对于网络图的绘制,一般我们都会在R中生成边和点列表后导入到Cytoscape和Gephi等的本地工具软件当中,而R语言中也自带有不少优秀的包也可精美的可视化我们的数据,所有函数也比较简单,有时间的不妨学习一下~~

加载R包

## 安装加载数据
if(!require(devtools)) install.packages("devtools")
devtools::install_github("kassambara/navdata")
install.packages(
  c("tidyverse", "igraph", "tidygraph", "ggraph")
)

library(pacman)
p_load("navdata","tidyverse", "igraph", "tidygraph", "ggraph")
  • navdata:需要用到此包中的示例数据集phone.call
  • tidyverse:数据进行操作转换
  • igraph,tidygraph和ggraph:用于网络可视化

查看示例数据

文件包含三列数据:来源地、目的地、及call数量

library("navdata")
data("phone.call")
head(phone.call, 3)
## # A tibble: 3 x 3
##    source destination n.call
##              
## 1  France     Germany      9
## 2 Belgium      France      4
## 3  France       Spain      3

我们都知道可视化网络,需要准备两个数据文件:

  • 点列表:包含点标签和其它的点属性
  • 边列表:包含点与点之间的关系,及其它属性

接下来基于此数据集准备点和边列表文件

点列表

  • 去重source 和 destination列,然后将向量合并一列命名为label,添加索引值
#  来源地去重
sources <- phone.call %>%
  distinct(source) %>%
  rename(label = source)
  
#目的地去重
destinations <- phone.call %>%
  distinct(destination) %>%
  rename(label = destination)
  
## 合并数据并添加一列索引
nodes <- full_join(sources, destinations, by = "label") 
nodes <- nodes %>%
  mutate(id = 1:nrow(nodes)) %>%
  select(id, everything())
head(nodes, 3)

## # A tibble: 3 x 2
##      id   label
##      
## 1     1  France
## 2     2 Belgium
## 3     3 Germany

创建边列表

  • 其实原始数据已具备边列表的格式,重命名 n.call为weight,然后通过left_join函数将点列表中id数据和边列表中进行合并
# Rename the n.call column to weight
phone.call <- phone.call %>%
  rename(weight = n.call)
  
# (a) Join nodes id for source column
edges <- phone.call %>% 
  left_join(nodes, by = c("source" = "label")) %>% 
  rename(from = id)
  
# (b) Join nodes id for destination column
edges <- edges %>% 
  left_join(nodes, by = c("destination" = "label")) %>% 
  rename(to = id)
  
# (c) Select/keep only the columns from and to
edges <- select(edges, from, to, weight)
head(edges, 3)

## # A tibble: 3 x 3
##    from    to weight
##      
## 1     1     3      9
## 2     2     1      4
## 3     1     8      3

可视化网络

至此,简单的边和点列表已经准备好了,我们接下来通过几个R包来可视化下

igraph

这是R中绘制网络图的一个基本R包,这里主要用到graph_from_data_fram()函数。更多关于此包绘图的细节可参考这个帖子Network Analysis and Visualization with R and igraph (kateto.net),介绍的十分详细。

library(igraph)
net.igraph <- graph_from_data_frame(
  d = edges, vertices = nodes, 
  directed = TRUE
  )
  ## d 边列表,vertices 点列表,directer:有向或者无向
  
  ## network
  set.seed(123)
plot(net.igraph, edge.arrow.size = 0.2,
     layout = layout_with_graphopt)
image-20220308151413493

tidygraph和ggraph

这两个R包目前相对比较流行,可以对network数据进行操作和可视化

  1. 首先用tidygraph创建networ对象
library(tidygraph)
net.tidy <- tbl_graph(
  nodes = nodes, edges = edges, directed = TRUE
  )
  1. 使用ggraph可视化网络
library(ggraph)
ggraph(net.tidy, layout = "graphopt") + 
  geom_node_point(col = 'gold',size = 2) + # 点信息
  geom_edge_link(aes(width = weight), alpha = 0.8) +  # 边信息
  scale_edge_width(range = c(0.2, 2)) + # 控制粗细
  geom_node_text(aes(label = label), repel = TRUE) + # 增加节点的标签,reple避免节点重叠
  labs(edge_width = "phone.call") + # 图例标签
  theme_graph()
image-20220308152100483

更多图形样式

  • 弧形图
# Arc diagram
ggraph(net.tidy, layout = "linear") + 
  geom_edge_arc(aes(width = weight), alpha = 0.8) + 
  scale_edge_width(range = c(0.2, 2)) +
  geom_node_text(aes(label = label), repel = TRUE) +
  labs(edge_width = "Number of calls") +
  theme_graph()+
  theme(legend.position = "top") 
linear
  • 弦图
# Coord diagram, circular
ggraph(net.tidy, layout = "linear", circular = TRUE) + 
  geom_edge_arc(aes(width = weight), alpha = 0.8) + 
  scale_edge_width(range = c(0.2, 2)) +
  geom_node_text(aes(label = label), repel = TRUE) +
  labs(edge_width = "Number of calls") +
  theme_graph()+
  theme(legend.position = "top")
image
  • treemap、dendrogram等等
Treemap
dendrogram

ggraph包还有更多好玩的样式,详情参考:https://www.data-imaginist.com/2017/ggraph-introduction-layouts/, 根据个人的数据去选择最合适的展现形式即可。

visNetwor和network3D

这两款R包都是基于浏览器的JavaScript可视化库,用于交互式的展示图形,这里我们还用到刚才的示例数据来展示。

加载数据

library(tidyverse)
library("navdata")
data("phone.call2")
nodes <- phone.call2$nodes
edges <- phone.call2$edges
## 刚才数据集是phone.call,phone.call2可以直接提取点和边列表

##注意:该包中节点和边缘列表中的ID应该是从0开始的数字值。我们直接减1 即可
nodes_d3 <- mutate(nodes, id = id - 1)
edges_d3 <- mutate(edges, from = from - 1, to = to - 1)

network3D

常用来快速创建交互式桑基图、和其它种类的网络图等,核心的函数即forceNetwork()

library(networkD3)
forceNetwork(
  Links = edges_d3, Nodes = nodes_d3,bounded = T,
  Source = "from", Target = "to",      # so the network is directed.
  NodeID = "label", Group = "id", Value = "weight", 
  width = 700, height=500,legend = T,
  colourScale = JS("d3.scaleOrdinal(d3.schemeCategory10);"), ## 颜色模板
  opacity = 1, fontSize = 18, zoom = TRUE, opacityNoHover = 1  ## 显示标签信息
)

## 如果想自定义颜色新修改,直接括号中改为16进制颜色即可
 colourScale = JS("d3.scaleOrdinal([`#383867`, `#584c77`, `#e1eff7`,`#dd2c29`]);"),
image-20220308160944163

制作桑基图

sankeyNetwork(
  Links = edges_d3, Nodes = nodes_d3, 
  Source = "from", Target = "to", 
  NodeID = "label", Value = "weight", 
  fontSize = 16, unit = "Letter(s)")
image-20220308161022262

visNetwork

该包绘制更加方便,

library(visNetwork)
visNetwork(nodes, edges) %>%
  visLayout(randomSeed = 12) 
image-20220308161618459

我们也可以为网络中的边添加方向,用到 layout_with_fr 方式

visNetwork(nodes, edges) %>% 
  visIgraphLayout(layout = "layout_with_fr") %>% 
  visEdges(arrows = "middle") %>%
  visLayout(randomSeed = 1234)  
image-20220308161805871
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容