6

One of the possible packages for interactive 3D plots is rgl. What I would like to do is to build 3D scatterplot with color coding according to some factor variable. The 3D dimensional scatterplot is for resulting loadings from plsr analysis.

The resulting plot looks like

3D scatterplot of PLS loadings with color coding according to the groups of variables

The example data is given in a table:

> loadings

      |      Comp 1         |        Comp 2            |    Comp 3           | Class
-------------------------------------------------------------------------------------------                    
TEMP  | -0.0607044182964255 | "0.0437618450165671"     |"0.045124991801441"  | "global"  
MW    | "-0.13414890573833" |   "-0.0970537799069731"  |0.263043734662182"   | "local" 
DM    |"-0.183751529577861" |  "-0.102703237685933"    |"0.0640549385564205" | "global" 
CHG   |"-0.0558781715833019"| "0.125155347350922"      |"-0.119258450107321" | "local"

or can be generated:

loadings <- data.frame(Comp1 = c(1.2, 3.4, 5.6, 13.1), Comp2 = c(4.3, 1.2, 7.7, 9.8),
                       Comp3 = c(1.2,6.9,15.6,15.0), 
                       row.names = c("TEMP", "MW", "DM", "CHG"), 
                       Class = c("global", "local", "global", "local"))
scatter3d(x=loadings[[1]], y=loadings[[2]], z=loadings[[3]], 
          point.col = as.numeric(as.factor(loadings[,4])), size = 10)

Obtained plot has the same style, but is much simpler as there are only two levels of variable "Class": 'global' and 'local'

enter image description here

Question is: Is it any possibility to add legend within rgl or maybe some independent legend can be attached to the plot? Thanks in advance for help!

Answer is:

scatter3d(x=loadings[[1]], y=loadings[[2]], z=loadings[[3]], 
          point.col = as.numeric(as.factor(loadings[,4])), size = 10, type = 's')
text3d(x=1.1, y=c(.9,1), z=1.1,levels(loadings[[4]]),col="black")
points3d(x=1.2,y=c(.9,1),z=1.1, col=as.numeric(as.factor(loadings[,4])), size=5)

The plot with labels according to classes: enter image description here

IRTFM
  • 258,963
  • 21
  • 364
  • 487
Boddha
  • 171
  • 2
  • 9
  • Please add the code and if possible data (either real or made-up) to your question so as to make a [minimum reproducible example](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). – SlowLearner Sep 27 '13 at 09:05
  • That new code throws an error: "Error in complete.cases(x, y, z) : ...". P – IRTFM Sep 28 '13 at 17:17

2 Answers2

1

That's not a plot3d image (unless perhaps you have another package loaded) , but looks like a scatter3d rendering constructed with the scatter3d function from the car package by John Fox:

  require(rgl)
  require(car)
  scatter3d(x=loadings[[1]], y=loadings[[2]], z=loadings[[3]], 
            point.col = as.numeric(as.factor(loadings[,4])), size = 10)

The scatter3d function does depend on rgl functions but has quite a few customization options. You offered no code to construct a "legend", so I played around with the example offered in rgl::text3d:

 text3d(1+ font/8, 1+cex/4, 1+famnum/8, text=paste(family, font), adj = 0.5, 
       color="blue", family=family, font=font, cex=cex)

enter image description here

With the new data this is in response to the request for text and points:

 scatter3d(x=loadings[[1]], y=loadings[[2]], z=loadings[[3]], 
             point.col = as.numeric(as.factor(loadings[,4])), size = 10)
 text3d(x=1.1, y=c(.9,1,1.1), z=1.1, names(loadings) ,col="black")
 points3d(x=1.2,y=c(.9,1,1.1),z=1.1, col=as.numeric(as.factor(loadings[,4])), size=5)

enter image description here

IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • yes, it is indeed scatter3d, fixed it. Well, it looks nice, but weird and not very informative. check out the text. and I need to have color labels, corresponding to color labels of data points, in the legend. – Boddha Sep 28 '13 at 15:56
  • It should not be too difficult to plot points and text in a structured manner as demonstrated. You do need to describe what is desired in detail. – IRTFM Sep 28 '13 at 16:59
1

I used the formula method to create groups, and 'removed' the group labels by turning them white because I could not figure out how to do this an easier way. Then I created a legend using legend3d ... which was very simple. Just make sure point and legend colours match. Maybe this is clunky, but it did what I needed it to do!

scatter3d(Biomass~Salinity*Moisture|Competitor, data=phrag19, labels=FALSE,
    surface=FALSE,
      grid = FALSE, 
        ellipsoid = FALSE,
    axis.col = c("black", "black", "black"),
    text.col=c("white","white","white","white","white","white","white"),
    surface.col=c("#1D1B1A","#C70039", 
"#94CC00","#A5D7F3","#D2A7DC","#1CAD7A","#FFB114"))

legend3d("right", legend = levels(phrag19$Competitor),
   col =  c("#1D1B1A","#C70039", "#94CC00","#A5D7F3","#D2A7DC","#1CAD7A","#FFB114"), 
pch = 18)

legend3d

Martin Mächler
  • 4,619
  • 27
  • 27