Question

I am making a PCA with vegan{} and I would also like to label my points by factors (instead of by their unique row identities, as is the default for biplot.rda()). For my 2D PCAs I have used the method suggested here by Gavin Simpson. I would like to ask the wise R community whether there is a 3D version of this method for creating a custom-labeled PCA. Here's the method that works for 2D PCAs:

#Relabel a la Gavin Simpson:
site.scr<-scores(dat.pca,display="sites",scaling=2,choices=c(1,2,3))
spp.scr<-scores(dat.pca,display="species",scaling=2,choices=c(1,2,3))

## generate x,y lims
xlims <- range(site.scr[,1], spp.scr[,1])
ylims <- range(site.scr[,2], spp.scr[,2])

## plot what you want, but leave out sites
biplot(dat.pca, display = "species", xlim = xlims, ylim = ylims)
points(site.scr[39:65,2:3],col="green",pch=1)   #These sites are in green
points(site.scr[1:38,2:3],col="brown",pch=3)        #These sites are in brown

I have done this using ordirgl() on one of my computers, but there are some R version/OS combos that don't play well with rgl (this seems to be an issue for a number of people), so I want to be able to make the plot in both rgl() and ordiplot3d()

ordiplot3d(dat.pca, display = "species", scaling = 3)

This plots points onto the 3D space instead of the vectors that biplot.rda (first issue-- I also have this problem when I use rgl-- I think these points are the ends of the vectors that plot in a normal biplot.rda() PCA). This is not as much of a concern to me, but if anyone knows how to draw these vectors in ordirgl and label them, I'd like to know. The bigger issue is that I am having a hard time adding points to ordiplot3d once it's made. Ideally this would be something like points(). I've seen this in a few different question threads, but it would be nice to have an elegant solution that doesn't require rgl.

Was it helpful?

Solution

First a warning; at the moment the underlying code used to draw the 3d biplots (package scatterplot3d) does not allow us to scale all axes the same. Hence the biplot is not correct as the third dimension cannot be scaled in the same units as the other two. Jari has provided a patch to the maintainer of the scatterplot3d package that allows this to be controlled but we are waiting on it being accepted etc.

What you are missing is that ordiplot3d() (because of its use of scatterplot3d()) returns an object that contains functions that allow you to add points etc to an existing 3d scatterplot.

Here is an example

## continue example from ?biplot.rda
require(vegan)
## produces 'mod' 
example(biplot.rda)
## why do we need this?
par(ask = FALSE)

## grab the scores on axes you require; mod == your fitted rda/pca 
site.scr <- scores(mod, display = "sites", scaling = 3, choices = 1:3) 
spp.scr <- scores(mod, display = "species", scaling = 3, choices = 1:3)

## do the 3d plot but suppress plotting of the species,
## though plot is scaled to accommodate them
ordi <- ordiplot3d(mod, display = "species", scaling = 3, type = "n")

Now look at the object ordi it is a complex object returns functions that allow you to add points to the current plot:

> str(ordi, max = 1)
List of 7
 $ xyz.convert   :function (x, y = NULL, z = NULL)  
 $ points3d      :function (x, y = NULL, z = NULL, type = "p", ...)  
 $ plane3d       :function (Intercept, x.coef = NULL, y.coef = NULL, lty = "dashed", lty.box = NULL, 
    ...)  
 $ box3d         :function (...)  
 $ origin        : num [1, 1:2] 1.67 1.33
 $ envfit.convert:function (object)  
 $ points        : num [1:30, 1:2] -0.146 2.776 1.291 3.102 2.816 ...
  ..- attr(*, "dimnames")=List of 2
 - attr(*, "class")= chr [1:2] "ordiplot3d" "ordiplot"

Now by way of illustration, plot the first 10 species with a colour and a a circle, second ten with a different colour and plotting character etc. using the points3d() returned:

cols <- bgs <- c("red","green","blue")
pchs <- 21:23
ordi$points3d(spp.scr[1:10,1], spp.scr[1:10,2], spp.scr[1:10,3],
              col = cols[1], bg = bgs[1], pch = pchs[1])
ordi$points3d(spp.scr[11:20,1], spp.scr[11:20,2], spp.scr[11:20,3],
              col = cols[2], bg = bgs[2], pch = pchs[1])
ordi$points3d(spp.scr[21:30,1], spp.scr[21:30,2], spp.scr[21:30,3],
              col = cols[3], bg = bgs[3], pch = pchs[3])

which produces:

example of adding points to a 3d scatterplot

Though do please note that this is not a real biplot as the scaling on the 3rd axis (z) is wrong until the ability to have equal scaling is added to scatterplot3d().

OTHER TIPS

I have written a small package called pca3d (http://cran.r-project.org/web/packages/pca3d/index.html) which also can create 3D biplots. I scales the samples and the variables independently, therefore the variable loadings are directly comparable. However, it is beta, so beware.

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top