I'm interested in this too, so I studied a bit and came up with an incomplete answer. This will produce an ellipsoid and mark its radii, but I haven't figured out how to rotate it using the eigenvectors.
Loading the rgl
package and running demo(shapes3d)
will give you this ellipsoid3d
function:
ellipsoid3d <- function(rx=1,ry=1,rz=1,n=30,ctr=c(0,0,0),
qmesh=FALSE,
trans = par3d("userMatrix"),...) {
if (missing(trans) && !rgl.cur()) trans <- diag(4)
degvec <- seq(0,pi,length=n)
ecoord2 <- function(p) {
c(rx*cos(p[1])*sin(p[2]),ry*sin(p[1])*sin(p[2]),rz*cos(p[2])) }
v <- apply(expand.grid(2*degvec,degvec),1,ecoord2)
if (qmesh) v <- rbind(v,rep(1,ncol(v))) ## homogeneous
e <- expand.grid(1:(n-1),1:n)
i1 <- apply(e,1,function(z)z[1]+n*(z[2]-1))
i2 <- i1+1
i3 <- (i1+n-1) %% n^2 + 1
i4 <- (i2+n-1) %% n^2 + 1
i <- rbind(i1,i2,i4,i3)
if (!qmesh)
quads3d(v[1,i],v[2,i],v[3,i],...)
else return(rotate3d(qmesh3d(v,i,material=list(...)),matrix=trans))
}
For demonstration, I'll use this covariance matrix:
$$\left(\begin{array} {cc}2.2&.4&.2\\.4&2.8&.3\\.2&.3&2.4\end{array}\right)$$
Covariance.Matrix=matrix(c(2.2,.4,.2,.4,2.8,.3,.2,.3,2.4),3)
Eigenvalue.Roots=eigen(Covariance.Matrix)$values^.5->X
require(rgl)
wire3d(ellipsoid3d(X[1],X[2],X[3],qmesh=T),col='lightgreen')
axes3d("x",pos=c(0,0,0),at=c(0,X[1]),labels='',lwd=2,col='maroon')
axes3d("y",pos=c(0,0,0),at=c(0,X[2]),labels='',lwd=2,col='maroon')
axes3d("z",pos=c(0,0,0),at=c(0,X[3]),labels='',lwd=2,col='maroon')
Rotating the ellipsoid3d
object is possible by using rotate3d()
inside wire3d()
, but I'm not sure how to find the angles $\phi,\theta,\psi$ from the eigenvectors. This is my best guess so far (based on this):
Phi=with(eigen(Covariance.Matrix),atan(vectors[3,2]/vectors[3,1]))
Theta=acos(eigen(Covariance.Matrix)$vectors[3,3])
Psi=with(eigen(Covariance.Matrix),atan(vectors[2,3]/-vectors[1,3]))
If these are known, the euler
function given here may help produce a matrix for rotate3d
's matrix
argument...but I'm not sure it works. With sample data, I seem to get a different rotation using John Fox's scatter3d
function. If you have a dataset of observation trios, not just a covariance matrix, scatter3d
seems to work well.
Best Answer
pnorm(z)
will do it.Or if you insist on a percentile, boom. Then try