已解决:查看我的解决方案,添加在帖子底部。
我目前正在尝试使用 r 创建一个圆形二分图,最好使用 ggraph。我有一个雄性和雌性青蛙交配关系的数据集;这是该数据的一个子集:
Mother Father
M1 F1
M2 F2
M3 F2
M4 F3
M5 F4
M6 F4
M7 F4
我的目标是可视化每个有机体拥有的伙伴数量,如下所示:
到目前为止,我已经能够使用 igraph 制作图形的线性版本:
> library(tidyverse)
> library(igraph)
> library(ggraph)
> MyData <- read_csv("Bipartite.csv")
> Visualization <-graph.data.frame(MyData)
> bipartite.mapping(Visualization)
$res
[1] TRUE
$type
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
TRUE TRUE TRUE
[14] TRUE TRUE TRUE TRUE TRUE TRUE TRUE
> V(Visualization)$type <- bipartite_mapping(Visualization)$type
> plot(Visualization, layout = layout.bipartite)
产生这个: 线性二分图显示母亲和父亲之间的交配关系;由于标签重叠,非常纠结且难以阅读
我坚持将其转换为圆形可视化。我尝试过的两件事是:
首先,将 igraph 对象带入 ggraph 并使用“圆形”布局进行绘制:
> ggraph(Visualization, layout = 'circle')
+ geom_edge_link()
+ geom_node_point()
但是我得到的不是两个同心环,而是一个大圆圈,这对于显示数据没有用(我知道,通过 ggraph 可以更简单地完成)。
其次,我尝试将 igraph 对象带入 ggraph 并将循环设置为 TRUE:
ggraph(Visualization, layout = 'bipartite', circular = TRUE)
+ geom_edge_link()
+ geom_node_point()
但我收到错误消息:
Error in layout_igraph_igraph(graph, layout, circular, ...) :
Circular layout only applicable to tree and DAG layout
关于如何产生我正在寻找的可视化的任何想法?我对 r 和 stackoverflow 都很陌生,所以对于对我的问题的解释有任何限制,我深表歉意。谢谢!
解决方案:
首先,加载您需要的包。
library(tidyverse)
library(tidygraph)
library(igraph)
library(ggraph)
现在,读入你的节点和边数据,并用 ggraph 构造图形对象。
Nodes <- read_csv("Nodes.csv")
Edges <- read_csv("Edges.csv")
Graph <- tbl_graph(nodes = Nodes, edges = Edges)
接下来,使用二分布局创建一个表示您的图形的对象。
g <- Graph
V(g)$type <- bipartite_mapping(g)$type
基于该二分图对象,我们将找到将节点排列成同心圆的每个节点的 x 和 y 坐标。首先,使用 create_layout 创建一个对象“coords”,它描述了当前的二分布局。coords 包含线性二分图中每个节点的 x 和 y 坐标列。
coords <- create_layout(g, layout = "bipartite") %>%
接下来,我们将使用一些三角函数将 x 和 y 坐标从线性二部图的坐标更改为描述圆形图的 x 和 y 坐标。首先,选择 x 和 y 列。
select(x, y) %>%
这条线创建了一个列,“theta”,它基本上根据我们需要沿圆边缘放置的节点数将单位圆划分为多个切片,并为每个节点分配一个切片。
mutate(theta = x / (max(x) + 1) * 2 * pi,
接下来的行创建 r 值,节点将被放置的圆的半径,并在笛卡尔平面上找到 x 和 y 坐标,该平面将沿着圆的边缘放置每个节点。
r = y + 1,
x = r * cos(theta),
y = r * sin(theta))
现在我们创建一个全新的图形布局,它根据我们刚刚在坐标中创建的那些圆坐标给出节点位置。
my_graph <- create_layout(g, "manual", node.position = coords)
我还想确保每个节点的标签以逻辑方式旋转,以便没有标签重叠并且所有标签都易于阅读。为此,首先根据“坐标”创建一个名为“label_data”的对象。
label_data <- coords
通过将 theta 列从弧度转换为度数,向 label_data 添加一个新列,称为“角度”。
label_data$angle <- (label_data$theta)*(180/pi)
如果我们只使用这个角度值,那么圆的第三和第四象限中的标签就会颠倒过来。因此,我们将这些区域的角度值转换为将它们正面朝上翻转。
label_data$plottingangle<-ifelse(label_data$angle < 270 & label_data$angle > 90, label_data$angle - 180, label_data$angle)
最后,我们只绘制具有我们创建的布局的图形对象,指定 geom_node_text 美学中标签的旋转角度。多田!
ggraph(my_graph) + geom_edge_link(edge_colour = "gray73") + geom_node_point(size = 0.8) + geom_node_text(aes(label = IndividualID, angle = label_data$plottingangle), size = 3) + scale_shape_manual(values = c(0, 19)) + coord_fixed() + theme_graph()