How to create polar dendrogram in 3D in rgl window in R

问题描述 投票:0回答:1

我想在 R 的 rgl 窗口中创建 3D 极坐标树状图

我修改了代码here,它最初是为了创建一个 2D 树状图(非极坐标),以在 3D rgl 窗口中创建树状图:

a <- list()  # initialize empty object
# define merging pattern: 
#    negative numbers are leaves, 
#    positive are merged clusters (defined by row number in $merge)
a$merge <- matrix(c(-1, -2,
                    -3, -4,
                     1,  2), nc=2, byrow=TRUE ) 
a$height <- c(1, 1.5, 3)    # define merge heights
a$order <- 1:4              # order of leaves(trivial if hand-entered)
a$labels <- LETTERS[1:4]    # labels of leaves
class(a) <- "hclust"        # make it an hclust object
plot(a)                     # look at the result   

# Convert to a dendrogram object.
ad <- as.dendrogram(a)

# dend_data contains segment information
library(ggdendro)
dend_data <- dendro_data(ad, type = "rectangle")

nodes <- dend_data$segments
# Append z value of 0 so that the dendrogram lies in a 2D plane embedded in 3D space.
nodes_3d <- cbind(nodes, z = 0, zend = 0)
nodes_3d <- nodes_3d[,c(1, 2, 5, 3, 4, 6)]

# Convert nodes_3d to nodes_3dLong, which is used by segments3d function to draw lines.
colnames(nodes_3d) <- NULL
nodes_3da <- nodes_3d[,1:3]
nodes_3db <- nodes_3d[,4:6]
nodes_3dLong <- do.call(rbind, lapply(1:nrow(nodes_3d), 
    function(i) rbind(unlist(c(nodes_3da[i,])), 
                      unlist(c(nodes_3db[i,])))))
# Plot the dendrogram in 3D.
library(rgl)
open3d()
segments3d(nodes_3dLong)

以上代码(完全可重现)在 rgl 窗口的 3D 空间中生成树状图。我想在 rgl 窗口中将此树状图转换为极坐标树状图。极地树状图仍应位于 3D 空间中的 2D 平面中。唯一的区别是它是极性树状图。对于二维图像,ggplot2 中的 coord_polar 用于创建极坐标树状图。但我不知道如何在 3D 中做到这一点。

附言转换为 3D 极坐标树状图后,我想通过 translate3d 在指定位置添加 3D 网格。因此,我希望任何解决方案都可以通过添加新的 3D 网格来进一步编辑此 3D 极地树状图。谢谢。

r 3d dendrogram rgl
1个回答
0
投票

这里有一些代码通过向其添加极坐标来转换计算中的

nodes
变量,然后使用它绘制树:

a <- list()  # initialize empty object
# define merging pattern: 
#    negative numbers are leaves, 
#    positive are merged clusters (defined by row number in $merge)
a$merge <- matrix(c(-1, -2,
                    -3, -4,
                    1,  2), nc=2, byrow=TRUE ) 
a$height <- c(1, 1.5, 3)    # define merge heights
a$order <- 1:4              # order of leaves(trivial if hand-entered)
a$labels <- LETTERS[1:4]    # labels of leaves
class(a) <- "hclust"        # make it an hclust object
plot(a)                     # show it

# Convert to a dendrogram object.
ad <- as.dendrogram(a)

# dend_data contains segment information
library(ggdendro)

dend_data <- dendro_data(ad, type = "rectangle")

nodes <- dend_data$segments

# Set the gap between the ends of the tree
gap <- 0
# Set the offset from the center.  
offset <- 0

radius <- with(nodes, max(c(y, yend)) + offset)
circ <- with(nodes, max(c(x, xend)) + gap)

# Convert to polar coordinates
nodes$theta <- with(nodes, 2*pi*x/circ)
nodes$thetaend <- with(nodes, 2*pi*xend/circ)
nodes$r     <- with(nodes, (radius - y)/radius)
nodes$rend  <- with(nodes, (radius - yend)/radius)

# Extract the horizontal and vertical segments
horiz <- subset(nodes, y == yend)
vert <- subset(nodes, x == xend)

library(rgl)

open3d()
#> glX 
#>   1

# Draw the vertical segments, which are still segments
x     <- with(vert, as.numeric(rbind(r*cos(theta), rend*cos(theta))))
y     <- with(vert, as.numeric(rbind(r*sin(theta), rend*sin(theta))))
segments3d(x, y, z = 0)

# Draw the horizontal segments, which are now arcs.  Zero
# radius arcs are dropped
horiz <- subset(horiz, r > 0)
with(horiz, arc3d(from = cbind(r*cos(theta), r*sin(theta), 0),
                  to = cbind(r*cos(thetaend), r*sin(thetaend), 0),
                  center = c(0, 0, 0)))

# Draw the labels
labels <- dend_data$labels
labels$theta <- with(labels, 2*pi*x/circ)
# Add a bit to the y so the label doesn't overlap the segment
labels$r     <- with(labels, (radius - y)/radius + 0.1)
with(labels, text3d(r*cos(theta), r*sin(theta), 0, label))

# Draw a circle around the whole thing
margin <- 0.25  # The gap below the leaves
theta <- seq(from = 0, to = 2*pi, length = 50)
r <- 1 + margin
lines3d(r*cos(theta), r*sin(theta), 0)

创建于 2023-04-12 与 reprex v2.0.2

标签的定位应该给你一个关于如何定位你的网格的提示。

顺便说一句,此代码中可能存在一个错误:如果任何弧线超过圆的一半,它们将被绘制在错误的方向上。如果这是一个问题,请将这些部分分成几个弧形。

© www.soinside.com 2019 - 2024. All rights reserved.