加载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)
tidygraph和ggraph
这两个R包目前相对比较流行,可以对network数据进行操作和可视化
- 首先用tidygraph创建networ对象
library(tidygraph) net.tidy <- tbl_graph( nodes = nodes, edges = edges, directed = TRUE )
- 使用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()
更多图形样式
- 弧形图
# 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")
- 弦图
# 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`]);"),
制作桑基图
sankeyNetwork( Links = edges_d3, Nodes = nodes_d3, Source = "from", Target = "to", NodeID = "label", Value = "weight", fontSize = 16, unit = "Letter(s)")
visNetwork
该包绘制更加方便,
library(visNetwork) visNetwork(nodes, edges) %>% visLayout(randomSeed = 12)
我们也可以为网络中的边添加方向,用到 layout_with_fr 方式
visNetwork(nodes, edges) %>% visIgraphLayout(layout = "layout_with_fr") %>% visEdges(arrows = "middle") %>% visLayout(randomSeed = 1234)