r - 三方图的水平布局
问题描述
我正在使用igraph
函数创建一个三方图,将讲师 ( ) 链接到参加该讲师指导的 3 个俱乐部A
的学生列表 ( B
to )。R
学生有 2 个班级的交叉成员资格,并且可能具有相同的性别。最后,边缘的宽度代表教练和每个学生在给定一周内平均投入每个俱乐部的时间。
创建图表很简单(我的代码在下面提供),但鉴于我的列表总共包含 17 名学生(B
to R
),最好通过将讲师(A
)放在顶部以水平方式呈现图表, 3 个俱乐部在中间,17 名学生 ( B
to 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
)
上面的代码生成了这个图。
然而我想要的输出应该是这样的
解决方案
感谢您的澄清。这更像是评论而不是答案。如果我按照您自己和评论者的建议运行代码:
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
但是,我确信有更好的方法可以做到这一点。
推荐阅读
- python - 使用自动调用 build() 方法在 Tensorflow 中创建层
- javascript - 空格和连字符分割字符串
- javascript - 用于工具 vue 的 css 过渡结束效果
- reactjs - navigation.goback() 缺少数据
- sql-server - 如何构建 Python 环境来部署 SSIS 包,或在本地运行 SSIS?
- node.js - visual-studio-code 无法在控制台中打印出二维数组,没有调试适配器,无法发送“变量”
- r - 按日期范围在 r 中绘图
- php - Stripe Api 错误:必须提供来源或客户
- javascript - 将匹配图像添加到随机消息 | 不和谐.js
- go - 我无法在 Go 的切片中更改结构变量的值