首页 > 解决方案 > 三方图的水平布局

问题描述

我正在使用igraph函数创建一个三方图,将讲师 ( ) 链接到参加该讲师指导的 3 个俱乐部A的学生列表 ( Bto )。R学生有 2 个班级的交叉成员资格,并且可能具有相同的性别。最后,边缘的宽度代表教练和每个学生在给定一周内平均投入每个俱乐部的时间。

创建图表很简单(我的代码在下面提供),但鉴于我的列表总共包含 17 名学生(Bto R),最好通过将讲师(A)放在顶部以水平方式呈现图表, 3 个俱乐部在中间,17 名学生 ( Bto R) 在底部。我怀疑这是因为我使用layout_with_sugiyama()了我的图表,但是任何人都可以提出替代方案来实现我想要的水平布局吗?

以下是我当前R用于此图的代码:

rm(list=ls())
library(foreign)
library(igraph)
library(dplyr)

### create tripartite node list and pairwise attributes
time <- data.frame(student = c("A", "A", "A", "B", "B", "B", "C", "C", "C", "D", "D", "D", "E", "E", "E", "F", "F", "F", "G", "G", "G", "H", "H", "H", "I", "I", "I", "J", "J", "J", "K", "K", "K", "L", "L", "L", "M", "M", "M", "N", "N", "N", "O", "O", "O", "P", "P", "P", "Q", "Q", "Q", "R", "R", "R"),
club = c("club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3", "club 1", "club 2", "club 3"), 
hours = c(10, 3, 6, 5, 2, 1, 3,	3, 2, 7, 5, 11,	1, 0, 3, 8, 2, 2, 2, 2,	0, 5, 7, 11, 1, 0, 1, 0, 1, 3, 8, 9, 2,	0, 0, 3, 4, 3, 6, 3, 1,	0, 3, 1, 7, 0, 0, 1, 0,	1, 5, 1, 3, 3))

### convert time dataframe into a graph object
df <- time[!time$hours == 0, ]
g <- graph_from_data_frame(df, directed = FALSE)
E(g)$width <- log(E(g)$hours)

### parse the data into three disjoint sets, use different node shapes to distinguish them

A <- "A"
club <- c("club 1", "club 2", "club 3")

V(g)$type <- 1
V(g)[name %in% club]$type <- 2
V(g)[name %in% "A"]$type <- 3
shape <- c("circle", "square", "circle")
size <- c(12, 15, 12)

### label class affiliation (except node A; G, K, L, Q do not belong to any classes)
Class1 <- c("B", "C", "E", "H", "J", "O")
Class2 <- c("D", "F", "M", "P", "I", "N", "R")

V(g)$color[V(g)$name] = "white"
V(g)$color[V(g)$name %in% Class1] = "red"
V(g)$color[V(g)$name %in% Class2] = "orange"
V(g)$color[V(g)$name == "A"] = "olivedrab1"

### highlight same sex nodes
s <- c("B", "D", "F", "G", "H", "K", "M", "P", "Q")
s_col = ifelse(V(g)$name %in% s,'black','grey80')

layout = layout_with_sugiyama(g, layers=V(g)$type)
V(g)$vertex_degree <-  igraph::degree(g)



plot(g,
     layout=cbind(V(g)$type, layout$layout[,1]), edge.curved=0,
     vertex.color = V(g)$color,
     vertex.label.color = "black",
     vertex.label.cex = 0.45,
     vertex.size = size[V(g)$type],
     vertex.shape = shape[V(g)$type],
     vertex.frame.color = s_col,
     edge.color= "grey30",
     asp = 1.3,
     edge.width = E(g)$width
)

上面的代码生成了这个图。

在此处输入图像描述

然而我想要的输出应该是这样的

在此处输入图像描述

标签: rdplyrigraphbipartite

解决方案


感谢您的澄清。这更像是评论而不是答案。如果我按照您自己和评论者的建议运行代码

plot(g,
     layout=cbind(V(g)$type, layout$layout[,1])[,2:1], edge.curved=0,
     vertex.color = V(g)$color,
     vertex.label.color = "black",
     vertex.label.cex = 0.45,
     vertex.size = size[V(g)$type],
     vertex.shape = shape[V(g)$type],
     vertex.frame.color = s_col,
     edge.color= "grey30",
     asp = 1.3,
     edge.width = E(g)$width
)

我得到以下输出:在此处输入图像描述

这与你试图完成的事情有什么不同?

编辑: 在 x 轴上找到更好看的顶点分布的一种方法是使用以下cut函数:

idx <- which(layout$layout[,2] == 2)  # find "club"-vertices
cuts <- layout$layout[idx, 1]         # find x-coords of vertices
cut(cuts, length(idx))                # cut into 3 intervals
layout$layout[idx,1] <- c(6,7.5,9)    # manually calculated even spans between x-coords

但是,我确信有更好的方法可以做到这一点。


推荐阅读