ggplot2是R语言中一个非常流行的数据可视化包,它也可以用于网络可视化。以下是三个基于ggplot2并专门用于网络可视化的R包:
ggnet2: 这个包的使用方法与传统的
plot
函数相似,易于使用。更多信息可在其官方页面查看:ggnet2geomnet: 这个包在ggplot2中增加了
geom_net
层,可以使用数据框作为输入,并且可以与Plotly交互,从而支持交互式图形。有关更多信息,请访问:geomnet on GitHub 和 geomnet on CRANggnetwork(首选): 这个包是三者中最灵活的,特别适合动态网络的可视化。它结合了ggplot2的优雅语法和网络数据的处理能力。更多信息可在其官方页面查看:ggnetwork
一、三个R包的比较
这三个包虽然都基于ggplot2进行网络可视化,但各有侧重和特点。您可以通过以下链接查看这三个包的详细比较:Comparison among ggnet2, geomnet, and ggnetwork
ggnet2 以其简单的语法和易用性而受到欢迎。
geomnet 通过增加可与ggplot2兼容的图层以及支持交互式图形(如与Plotly的整合),提供了额外的灵活性和功能。
ggnetwork 由于其在处理动态网络方面的优势,是最灵活的选择,适合需要高度定制化网络图的用户。
二、示例数据分析
这段文本提供了在R语言环境中使用多个包来处理和可视化足球比赛数据的例子。以下是步骤的详细说明:
2.1 安装和加载必要的包
这部分代码涉及安装并加载处理网络数据的几个R包。
GGally
、geomnet
、ggnetwork
和statnet
都是处理图形和网络数据的强大工具。
# 安装包
#install.packages("GGally")
#install.packages("geomnet")
#install.packages("ggnetwork")
# 加载包
library("GGally")
library("geomnet")
library("ggnetwork")
library("statnet")
2.2 加载数据
这里,数据集
football
来自geomnet
包,包含足球队之间的比赛信息。
# 加载数据
data("football", package = "geomnet")
rownames(football$vertices) <- football$vertices$label
2.3 创建网络
使用边列表
football$edges[,1:2]
创建一个网络结构,这里用的是network::network()
函数。
# 从边列表创建网络
fb.net = network::network(football$edges[,1:2])
2.4 添加顶点和边的属性
为网络中的顶点(足球队)添加属性,指明每个队伍所在的会议。此外,还为边添加属性,表示两个队伍是否属于同一会议。
# 添加顶点属性:队伍所在的会议
fb.net %v% "conf" <- football$vertices[network.vertex.names(fb.net), "value"]
# 添加边属性:两队是否同属一个会议
set.edge.attribute(fb.net, "same.conf", football$edges$same.conf)
set.edge.attribute(fb.net, "lty", ifelse(fb.net %e% "same.conf" == 1, 1, 2))
三、ggnet2
ggnet2是一个用于网络可视化的R包,它的特点如下:
3.1 功能特点
输入:网络对象
提供详细教程:ggnet2 教程
语法类似于plot:使用简单,语法与传统的绘图函数类似
输出:输出底层的组织结构(节点的位置),便于添加
geom_xx
层
3.2 问题
不支持曲线边缘
不支持自环
不适用于复杂图形
对于变化的图表,不能直接提供多个面板。需要固定放置坐标。
3.3 示例代码
设置种子,确保结果的可重现性,并使用ggnet2来创建一个网络图表的示例。
set.seed(3212019)
pggnet2 = ggnet2(fb.net, # 输入 `network` 对象
mode = "fruchtermanreingold", # 来自 `network` 包的布局
layout.par = list(cell.jitter=0.75), # 可以传递布局参数
# 节点属性
node.color = "conf",
palette = "Paired", # 颜色板 palette="Set3",
node.size = 5,
# node.size = "degree",
# size.cut = 3, # 使用分位数将大小切割为三个类别
# size = "conf",
# 手动映射大小:size.palette = c("Atlantic Coast" = 1,...),
# node.shape = "conf",
node.alpha = 0.5,
# node.label = TRUE,
# 边缘
edge.color = c("color", "grey50"), # 第一个值:同一组的节点使用相同颜色,否则使用第二个参数
edge.alpha = 0.5,
edge.size = 0.3,
edge.lty = "lty",
# edge.label = 1,
# edge.label.size = 1,
# 图例
color.legend = "Conference",
# legend.size = 10,
# legend.position = "bottom"
) +
geom_point(aes(color = color), size = 3) # 可以像ggplot对象一样处理并添加geom_xx层
pggnet2
## 将其作为数据框处理以添加geom_xx层
pggnet2$data %>% names()
## [1] "label" "alpha" "color" "shape" "size" "x" "y"
此代码段展示了如何使用ggnet2包来构建并自定义网络图表的外观,通过控制节点和边的颜色、大小、透明度等属性,以及如何在ggplot2框架下增加额外的图形层。
四、geomnet
geomnet 是一个基于 ggplot2 的 R 包,用于网络可视化,特点如下:
4.1 功能特点
输入:数据框
支持自环
支持面板(无法固定节点)
4.2 问题
没有提供详细的教程
底层结构不可用,被整体封装(例如:如果设置透明度,适用于节点和边缘;不提供点的位置)
严格遵守 ggplot2 语法,灵活性较差
4.3 示例代码
以下是一个合并顶点和边缘数据,并使用 geomnet 创建网络图的例子:
# 合并顶点和边
ver.conf = football$vertices %>% mutate(from = label) %>% select(-label)
fb.df = left_join(football$edges, ver.conf, by = "from")
# 创建数据图
set.seed(3212019)
pgeomnet =
ggplot(data = fb.df, # 输入:数据框
aes(from_id = from, to_id = to)) +
geom_net(layout.alg = 'fruchtermanreingold',
aes(colour = value, group = value,
linetype = factor(same.conf != 1)),
linewidth = 0.5,
size = 5, vjust = -0.75, alpha = 1) +
theme_net() +
# theme(legend.position = "bottom") +
scale_colour_brewer("Conference", palette = "Paired") +
guides(linetype = FALSE)
pgeomnet
五、ggnetwork
ggnetwork 是一个专门用于网络可视化的 R 包,具有以下特点:
5.1 特点
提供详细教程:ggnetwork 教程
输入:可以是 igraph(需要加载
intergraph
库)或 network 对象语法非常用户友好
ggnetwork 提供底层的数据框
使用
geom_edges
和geom_nodes
分别设置;可以在geom_xx
内设置针对边/节点的特定映射对于标签,支持
geom_(node/edge)(text/label)[_repel]
:如geom_nodetext
,geom_nodelabel
,geom_nodetext_repel
,geom_nodelabel_repel
,geom_edgetext
,geom_edgelabel
,geom_edgetext_repel
,geom_edgelabel_repel
允许曲线边缘(且与 plotly 兼容)
可以使用面板展示动态网络,并固定节点位置
5.2 问题
不支持自环
5.3 示例代码
这是一个使用 ggnetwork 包和 ggplot2 语法创建网络图的示例:
## 需要先安装 intergraph 包用于处理 igraph 对象
#install.packages("intergraph")
library("intergraph")
## 创建 igraph 对象
fb.igra = graph_from_data_frame(football$edges[,1:2], directed = FALSE)
V(fb.igra)$conf = football$vertices[V(fb.igra)$name, "value"]
E(fb.igra)$same.conf = football$edges$same.conf
E(fb.igra)$lty = ifelse(E(fb.igra)$same.conf == 1, 1, 2)
## 设置种子
set.seed(3212019)
## 使用 ggnetwork 和 ggplot 绘图
pggnetwork =
ggplot(
ggnetwork( # 提供底层数据框
fb.igra, # 输入:网络对象
layout = "fruchtermanreingold", # 布局
cell.jitter = 0.75
),
aes(x, y, xend = xend, yend = yend)
) +
geom_edges(
aes(linetype = as.factor(same.conf)),
color = "grey50",
curvature = 0.2,
alpha = 0.5
) +
geom_nodes(
aes(color = conf),
size = 5,
alpha = 0.5
) +
scale_color_brewer("Conference", palette = "Paired") +
scale_linetype_manual(values = c(2, 1)) +
guides(linetype = FALSE) +
theme_blank() +
geom_nodes(
aes(color = conf),
size = 3
) # 可以像 ggplot 对象一样处理并添加 geom_xx 层
pggnetwork
六、ggnet2、geomnet、ggnetwork 的扩展
由于这些工具的输出是 ggplot2 对象,它们可以与其他库如 plotly 结合,实现交互式网络可视化或动态网络可视化。
6.1 ggplot2 + plotly
使用 plotly 库,可以将 ggplot2 创建的静态图转换为交互式图表。以下是如何实现的:
6.2 加载 plotly 库
library("plotly")
6.3 将 ggplot2 对象转换为 plotly 对象
这里,
pggnet2
和pgeomnet
是使用 ggnet2 或 geomnet 创建的 ggplot2 图对象。通过使用ggplotly()
函数,我们可以添加coord_fixed()
来保持比例一致,并使用hide_guides()
隐藏不必要的图例和指南。
ggplotly(pggnet2 + coord_fixed()) %>% hide_guides()
ggplotly(pgeomnet + coord_fixed()) %>% hide_guides()
注意,如果设置了边的
curvature
属性,plotly 可能无法正确显示这一属性。例如,下面的代码中暂时注释了对pggnetwork
的转换:
# ggplotly(pggnetwork + coord_fixed()) %>% hide_guides()
6.4 创建新的网络图 pggnetwork2
下面的代码展示了如何使用 ggnetwork 创建一个网络对象,然后通过 ggplotly 转换为交互式图表。这里同样使用了
hide_guides()
来清洁图表的显示:
pggnetwork2 =
ggplot(
ggnetwork( # 提供底层数据框
fb.igra, # 输入:网络对象
layout = "fruchtermanreingold", # 布局
cell.jitter = 0.75
),
aes(x, y, xend = xend, yend = yend)
) + # 边的映射
geom_edges(
aes(linetype = as.factor(same.conf)),
color = "grey50",
alpha = 0.5
) +
geom_nodes(
aes(color = conf),
size = 5,
alpha = 0.5
) +
scale_color_brewer("Conference", palette = "Paired") +
scale_linetype_manual(values = c(2, 1)) +
guides(linetype = FALSE) +
theme_blank() +
geom_nodes(
aes(color = conf),
size = 3
)
ggplotly(pggnetwork2 + coord_fixed()) %>% hide_guides()
七、分面动态网络
推荐使用 ggnetwork 来创建分面动态网络。
7.1 创建网络
以下示例使用了一个电子邮件数据集,其中包括节点和边的相关属性。
# 查看电子邮件数据集的边和节点的属性名
names(email$edges)
## [1] "From" "eID" "Date" "Subject" "to"
## [6] "month" "day" "year" "nrecipients"
names(email$nodes)
## [1] "label" "LastName"
## [3] "FirstName" "BirthDate"
## [5] "BirthCountry" "Gender"
## [7] "CitizenshipCountry" "CitizenshipBasis"
## [9] "CitizenshipStartDate" "PassportCountry"
## [11] "PassportIssueDate" "PassportExpirationDate"
## [13] "CurrentEmploymentType" "CurrentEmploymentTitle"
## [15] "CurrentEmploymentStartDate" "MilitaryServiceBranch"
## [17] "MilitaryDischargeType" "MilitaryDischargeDate"
# 从电子邮件数据集中提取边列表:移除发送给所有员工的电子邮件
edges = email$edges %>% filter(nrecipients < 54) %>% select(From, to, day)
# 创建网络对象
em.net <- network(edges[, 1:2])
# 分配边的属性(天)
set.edge.attribute(em.net, "day", edges[, 3])
# 分配节点的属性(员工类型)
em.cet <- as.character(email$nodes$CurrentEmploymentType)
names(em.cet) = email$nodes$label
em.net %v% "curr_empl_type" <- em.cet[network.vertex.names(em.net)]
# 设置种子以确保可重复性
set.seed(3212019)
# 使用 ggnetwork 创建可视化
ggplot(
ggnetwork(
em.net,
arrow.gap = 0.02, # 箭头间隙
by = "day", # 按天分面
layout = "kamadakawai" # 布局算法
),
aes(x, y, xend = xend, yend = yend)
) +
geom_edges(
aes(color = curr_empl_type),
alpha = 0.25,
arrow = arrow(length = unit(5, "pt"), type = "closed") # 定义箭头
) +
geom_nodes(aes(color = curr_empl_type), size = 1.5) + # 定义节点
scale_color_brewer("Employment Type", palette = "Set1") + # 颜色映射
facet_wrap(. ~ day, nrow = 2, labeller = "label_both") + # 分面显示
theme_facet(legend.position = "bottom") # 调整主题
注意:在运行代码时,如果检测到重复的边,可能会出现警告信息。这需要在数据预处理阶段进行检查和处理。
参考资料
https://briatte.github.io/ggnet/ https://cran.r-project.org/web/packages/ndtv/vignettes/ndtv.pdf