简体   繁体   中英

Overlapping labels with the plot3D package in R

I am currently creating a 3D scatterplot using the plot3D package in R, and I wanted to add data labels to my data points. However, some of my data points have the same values with each other, and I wanted to find a solution similar to ggrepel that would offset the data labels from the points so that the labels for those points would be legible. Sample code below:

library(plot3D)
names <- c("A", "B", "C", "D", "E")
x <- c(1,1,2,3,4)
y <- c(1,1,3,4,5)
z <- c(1,1,4,5,6)

scatter3D(x, y, z)
text3D(x,y,z, names, add = TRUE, cex = 1)

The labels for A and B are currently superimposed on top of each other.

I tried to use the directlabels package as well, and it doesn't seem to recognize the text3D or the plot3D objects. Any help would appreciated.

The plotrix::thigmophobe function works out directions to try to stop labels from overlapping in 2D plots. rgl doesn't have anything equivalent, and since you can rotate a plot, you'll always be able to rotate labels on top of each other. However, the function below makes an attempt to place labels for one particular view so that they don't overlap.

thigmophobe.text3d <- function(x, y = NULL, z = NULL, texts, ...) {
  xyz <- xyz.coords(x, y, z)

  # Get the coordinates as columns in a matrix in
  # homogeneous coordinates
  pts3d <- rbind(xyz$x, xyz$y, xyz$z, 1)

  # Apply the viewing transformations and convert 
  # back to Euclidean
  pts2d <- asEuclidean(t(par3d("projMatrix") %*% 
                         par3d("modelMatrix") %*% 
                         pts3d))

  # Find directions so that the projections don't overlap
  pos <- plotrix::thigmophobe(pts2d)

  # Set adjustments for the 4 possible directions
  adjs <- matrix(c(0.5, 1.2,   
                   1.2, 0.5,  
                   0.5, -0.2,  
                  -0.2, 0.5), 
                 4, 2, byrow = TRUE)

  # Plot labels one at a time in appropriate directions.
  for (i in seq_along(xyz$x)) 
    text3d(pts3d[1:3, i], texts = texts[i], 
           adj = adjs[pos[i],], ...)
}

There are some problems with the function above: it is based on rgl::text3d rather than plot3D::text3D , so the optional arguments are different; it plots labels one at a time, which can be inefficient if you have a lot of labels, it doesn't do error checking, etc.

Edited to add:

The unreleased version 0.99.20 of rgl adds a thigmophobe3d function to do this. You'll have to get it from https://r-forge.r-project.org/R/?group_id=234 or the Github mirror https://github.com/rforge/rgl for now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM