Search code examples
rmatrix3drgl

3D plot in R using persp3D - Axis issues


I have a matrix (m) and I'm trying to plot a 3D representation of that matrix.

    > dput(head(m))

structure(c(21930, 21844, 21758, 21672, 21586, 21500, 22016, 
21930, 21844, 21758, 21672, 21586, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0), .Dim = c(6L, 26L), .Dimnames = list(
    NULL, c("freq.min", "freq.max", "X0", "X1", "X2", "X3", "X4", 
    "X5", "X6", "X7", "X8", "X9", "X10", "X11", "X12", "X13", 
    "X14", "X15", "X16", "X17", "X18", "X19", "X20", "X21", "X22", 
    "X23")))

I managed to plot a 3D surface plot, but both the axes and the axis labels are incorrect. Note that the 3D surface plot below uses the entire matrix rather than just the header, which I only include here as the dput for brevity.

persp3D(z = m[,3:26], col = "lightgrey", shade = 0.5, ticktype = "detailed", axes=T)

enter image description here

Let's start with the axes themselves: the axis that goes from X0 to X23 should be the X axis of the matrix (column names), but here it is regarded as the Y axis. The Y axis, regarded here as the X axis, ranges from 0 to 22016 in 256 intervals of 86.

I've spent the last many hours scouring the internet for answers on how to change the axis labels, but have not succeeded. From what I understand, if I turn off the axis argument in persp3D (axes=F) I can then customize the axis in a subsequent line, like so:

axis3d(edge= 'y+-', at =seq(0,23,by=1) ,
       labels = seq(0,23,by=1))

However, a RGL device pops up, and only the axis is plotted without the actual plot itself, which stays unchanged in the built-in R graphics device.

How do I successfully change the axes?


Solution

  • Does this what you're looking for?

    clab <- 0:23
    rlab <- seq(0, 21586, 86)
    
    cnum <- length(clab)
    rnum <- length(rlab)
    
    m <- matrix(
      c(runif(0.5*cnum*rnum)-1, runif(0.5*cnum*rnum)+1), 
      rnum, cnum, 
      dimnames = list(rlab, clab))
    
    library(rgl)
    
    plot3d(
      clab, rlab, t(m),
      type="n",
      aspect = c(100, 200, 20),
      xlab = "x", ylab = "y", zlab = "z",
      sub = "Grab me and rotate me!"
    )
    
    surface3d(
      clab, rlab, t(m),
      color = c("black", "white"),
      alpha = 0.5,
      add = TRUE
    )
    

    To change the axis you can interchange x and y and transpose z with t().

    As a side note: I wrote two functions to transform 3D point cloud data from tall to wide format and vice versa: recexcavAAR::spatialwide and recexcavAAR::spatiallong. I find them quite useful to go back and forth between plotting and analysis. Maybe they're useful for you.

    Edit: Alternative solution with single call to persp3d

    clab <- 0:23
    rlab <- seq(0, 21586, 86)
    
    cnum <- length(clab)
    rnum <- length(rlab)
    
    m <- matrix(
      c(runif(0.5*cnum*rnum)-1, runif(0.5*cnum*rnum)+1), 
      rnum, cnum, 
      dimnames = list(rlab, clab))
    
    library(rgl)
    
    persp3d(
      clab, rlab, t(m),
      color = c("black", "white"),
      alpha = 0.5,
      aspect = c(100, 200, 20),
      xlab = "x", ylab = "y", zlab = "z",
      sub = "Grab me and rotate me!"
    )