生成 igraph 布局时修复 y 坐标
Fix y-coordinate when producing igraph layout
我正在尝试使用 R 包 igraph
生成树状图。我从如下所示的邻接矩阵 Y 开始:
Y <- matrix(c(1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,
1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,
0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,
0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,1,
0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),
ncol=25)
然后我使用
创建图表
g <- graph_from_adjacency_matrix(Y,mode="undirected",diag=F)
现在我想绘制一个树状图,第一个节点位于树的顶部,为此我做了
L <- layout.reingold.tilford(g,root=1)
plot.igraph(g,layout=L)
结果看起来非常接近我正在寻找的结果,但现在我想为顶点使用自定义 y 坐标。原因是我希望 y 轴有意义:每个顶点都有一个 score
值,我希望 y 坐标与该分数成正比。当然我可以简单地使用
L[,2] <- score
问题是这样做会弄乱情节,出现重叠的顶点和相交的边,这是不可取的。我可以通过 tkplot
手动调整 x 坐标来解决它,但最终我将需要自动生成几张图并手动一张一张地检查它们是不可行的。
所以问题是,有没有什么方法可以使用预定义的顶点 y 坐标来获得 "optimal" 树图表示?
希望我说得够清楚了。提前感谢您的宝贵时间!
J
编辑:这就是我 dput
我的图形变量 g
得到的结果(请注意 scores
已添加为顶点属性,可以通过 V(g)$scores
)
> dput(g)
structure(list(25, FALSE, c(1, 2, 5, 4, 6, 3, 12, 8, 11, 13,
14, 17, 7, 9, 19, 20, 10, 18, 22, 24, 15, 16, 21, 23), c(0, 0,
0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 7, 7, 8, 8, 8, 8, 13, 13,
16, 16), c(0, 1, 5, 3, 2, 4, 12, 7, 13, 16, 8, 6, 9, 10, 20,
21, 11, 17, 14, 15, 22, 18, 23, 19), c(0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23),
c(0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24), c(0, 3, 5, 7, 9, 12,
14, 14, 16, 20, 20, 20, 20, 20, 22, 22, 22, 24, 24, 24, 24,
24, 24, 24, 24, 24), list(c(1, 0, 1), structure(list(), .Names = character(0)),
structure(list(name = c("GO:0008150", "GO:0050896", "GO:0044699",
"GO:0044767", "GO:0051716", "GO:0016043", "GO:0002544",
"GO:0071822", "GO:0048513", "GO:0007044", "GO:0007517",
"GO:0030855", "GO:0006816", "GO:0007165", "GO:0042178",
"GO:0007169", "GO:0009966", "GO:0070458", "GO:0090131",
"GO:0007052", "GO:0006335", "GO:2000587", "GO:0045653",
"GO:0070372", "GO:0003257"), scores = c(0, 0.301029995663981,
0.301029995663981, 0.602059991327962, 0.602059991327962,
0.602059991327962, 0.778151250383644, 0.778151250383644,
1, 1.04139268515822, 1.07918124604762, 1.07918124604762,
1.11394335230684, 1.11394335230684, 1.14612803567824,
1.20411998265592, 1.23044892137827, 1.25527250510331,
1.25527250510331, 1.27875360095283, 1.39794000867204,
1.50514997831991, 1.63346845557959, 1.70757017609794,
1.96378782734556), color = c("black", "black", "black",
"black", "black", "black", "red", "black", "black", "red",
"red", "red", "red", "black", "red", "red", "black",
"red", "red", "red", "red", "red", "red", "red", "red"
)), .Names = c("name", "scores", "color")), list()),
<environment>), class = "igraph")
由于 layout_with_sugiyama
没有用,我将提出更多的 hack,
或者更确切地说是两个黑客,一个建立在另一个之上。
首先,稍微打扫一下。使用 g 的 dput 版本,我收到警告
graph was created by an old(er) igraph version.
Call upgrade_graph() on it to use with the current igraph version
For now we convert it on the fly...
所以我从 g = upgrade_graph(g)
开始
接下来,当我绘制你的图表时,我发现很难阅读,因为
黑色节点上的海军文本。因此,我将您的节点更改为灰色。
如果您愿意,可以将其省略。
V(g)$color[V(g)$color == "black"] = "#888888"
现在我们需要布置图形。我会像你一样开始
Reingold-Tilford
L <- layout.reingold.tilford(g,root=1)
但这并没有使用你的scores
。当然,一个布局,只是给
节点的 x-y 位置,所以第一个技巧就是覆盖
y 值与你的分数。
L2 = L
L2[,2] = V(g)$scores
plot(g,layout=L2)
绘图区域的中心有点拥挤。所以我会
摆脱边缘。
par(mar=rep(0,4))
plot(g,layout=L2)
这还不错,但一些节点标签仍然重叠。
第二个技巧是我将只移动这些 "by hand"。
L3 = L2
L3[18,1] = -2.2
L3[19,1] = -1.1
L3[12,1] = 0
L3[13,1] = 1
plot(g,layout=L3)
此时,高度与您的分数成正比,并且没有标签重叠。
我正在尝试使用 R 包 igraph
生成树状图。我从如下所示的邻接矩阵 Y 开始:
Y <- matrix(c(1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,
1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,
0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,
0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,1,
0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),
ncol=25)
然后我使用
创建图表g <- graph_from_adjacency_matrix(Y,mode="undirected",diag=F)
现在我想绘制一个树状图,第一个节点位于树的顶部,为此我做了
L <- layout.reingold.tilford(g,root=1)
plot.igraph(g,layout=L)
结果看起来非常接近我正在寻找的结果,但现在我想为顶点使用自定义 y 坐标。原因是我希望 y 轴有意义:每个顶点都有一个 score
值,我希望 y 坐标与该分数成正比。当然我可以简单地使用
L[,2] <- score
问题是这样做会弄乱情节,出现重叠的顶点和相交的边,这是不可取的。我可以通过 tkplot
手动调整 x 坐标来解决它,但最终我将需要自动生成几张图并手动一张一张地检查它们是不可行的。
所以问题是,有没有什么方法可以使用预定义的顶点 y 坐标来获得 "optimal" 树图表示?
希望我说得够清楚了。提前感谢您的宝贵时间!
J
编辑:这就是我 dput
我的图形变量 g
得到的结果(请注意 scores
已添加为顶点属性,可以通过 V(g)$scores
)
> dput(g)
structure(list(25, FALSE, c(1, 2, 5, 4, 6, 3, 12, 8, 11, 13,
14, 17, 7, 9, 19, 20, 10, 18, 22, 24, 15, 16, 21, 23), c(0, 0,
0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 7, 7, 8, 8, 8, 8, 13, 13,
16, 16), c(0, 1, 5, 3, 2, 4, 12, 7, 13, 16, 8, 6, 9, 10, 20,
21, 11, 17, 14, 15, 22, 18, 23, 19), c(0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23),
c(0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24), c(0, 3, 5, 7, 9, 12,
14, 14, 16, 20, 20, 20, 20, 20, 22, 22, 22, 24, 24, 24, 24,
24, 24, 24, 24, 24), list(c(1, 0, 1), structure(list(), .Names = character(0)),
structure(list(name = c("GO:0008150", "GO:0050896", "GO:0044699",
"GO:0044767", "GO:0051716", "GO:0016043", "GO:0002544",
"GO:0071822", "GO:0048513", "GO:0007044", "GO:0007517",
"GO:0030855", "GO:0006816", "GO:0007165", "GO:0042178",
"GO:0007169", "GO:0009966", "GO:0070458", "GO:0090131",
"GO:0007052", "GO:0006335", "GO:2000587", "GO:0045653",
"GO:0070372", "GO:0003257"), scores = c(0, 0.301029995663981,
0.301029995663981, 0.602059991327962, 0.602059991327962,
0.602059991327962, 0.778151250383644, 0.778151250383644,
1, 1.04139268515822, 1.07918124604762, 1.07918124604762,
1.11394335230684, 1.11394335230684, 1.14612803567824,
1.20411998265592, 1.23044892137827, 1.25527250510331,
1.25527250510331, 1.27875360095283, 1.39794000867204,
1.50514997831991, 1.63346845557959, 1.70757017609794,
1.96378782734556), color = c("black", "black", "black",
"black", "black", "black", "red", "black", "black", "red",
"red", "red", "red", "black", "red", "red", "black",
"red", "red", "red", "red", "red", "red", "red", "red"
)), .Names = c("name", "scores", "color")), list()),
<environment>), class = "igraph")
由于 layout_with_sugiyama
没有用,我将提出更多的 hack,
或者更确切地说是两个黑客,一个建立在另一个之上。
首先,稍微打扫一下。使用 g 的 dput 版本,我收到警告
graph was created by an old(er) igraph version. Call upgrade_graph() on it to use with the current igraph version For now we convert it on the fly...
所以我从 g = upgrade_graph(g)
开始
接下来,当我绘制你的图表时,我发现很难阅读,因为
黑色节点上的海军文本。因此,我将您的节点更改为灰色。
如果您愿意,可以将其省略。
V(g)$color[V(g)$color == "black"] = "#888888"
现在我们需要布置图形。我会像你一样开始
Reingold-Tilford
L <- layout.reingold.tilford(g,root=1)
但这并没有使用你的scores
。当然,一个布局,只是给
节点的 x-y 位置,所以第一个技巧就是覆盖
y 值与你的分数。
L2 = L
L2[,2] = V(g)$scores
plot(g,layout=L2)
绘图区域的中心有点拥挤。所以我会 摆脱边缘。
par(mar=rep(0,4))
plot(g,layout=L2)
这还不错,但一些节点标签仍然重叠。 第二个技巧是我将只移动这些 "by hand"。
L3 = L2
L3[18,1] = -2.2
L3[19,1] = -1.1
L3[12,1] = 0
L3[13,1] = 1
plot(g,layout=L3)
此时,高度与您的分数成正比,并且没有标签重叠。