Nothing
#### ellipsoidhull : Find (and optionally draw)
#### ----------- the smallest ellipsoid containining a set of points
####
#### Just making the algorithms in clusplot() available more generally
#### ( --> ./plotpart.q )
### Author: Martin Maechler, Date: 21 Jan 2002, 15:41
ellipsoidhull <-
function(x, tol = 0.01, maxit = 5000,
ret.wt = FALSE, ret.sqdist = FALSE, ret.pr = FALSE)
{
if(!is.matrix(x) || !is.numeric(x))
stop("'x' must be numeric n x p matrix")
if(anyNA(x)) {
warning("omitting NAs")
x <- na.omit(x)
}
n <- nrow(x)
if(n == 0) stop("no points without missing values")
p <- ncol(x)
res <- .C(spannel,
n,
ndep= p,
dat = cbind(1., x),
sqdist = double(n),
l1 = double((p+1) ^ 2),
double(p),
double(p),
prob = double(n),
double(p+1),
eps = as.double(tol),
maxit = as.integer(maxit),
ierr = integer(1))# 0 or non-zero
if(res$ierr != 0)
cat("Error in Fortran routine computing the spanning ellipsoid,",
"\n probably collinear data\n", sep="")
if(any(res$prob < 0) || all(res$prob == 0))
stop("computed some negative or all 0 probabilities")
conv <- res$maxit < maxit
if(!conv)
warning(gettextf("algorithm possibly not converged in %d iterations", maxit))
conv <- conv && res$ierr == 0
cov <- cov.wt(x, res$prob)
## cov.wt() in R has extra wt[] scaling; revert here
res <- list(loc = cov$center,
cov = cov$cov * (1 - sum(cov$wt^2)),
d2 = weighted.mean(res$sqdist, res$prob),
wt = if(ret.wt) cov$wt,
sqdist = if(ret.sqdist) res$sqdist,
prob= if(ret.pr) res$prob,
tol = tol,
eps = max(res$sqdist) - p,
it = res$maxit,
maxit= maxit,
ierr = res$ierr,
conv = conv)
class(res) <- "ellipsoid"
res
}
print.ellipsoid <- function(x, digits = max(1, getOption("digits") - 2), ...)
{
d <- length(x$loc)
cat("'ellipsoid' in", d, "dimensions:\n center = (",
format(x$loc, digits=digits),
"); squared ave.radius d^2 = ", format(x$d2, digits=digits),
"\n and shape matrix =\n")
print(x$cov, digits = digits, ...)
Vx <- volume(x)
chV <- if(!is.finite(Vx))
paste0("exp(", format(volume(x, log=TRUE), digits=digits),")")
else
format(Vx, digits=digits)
cat(" hence,", if(d==2) "area" else "volume", " = ", chV, "\n")
if(!is.null(x$conv) && !x$conv) {
cat("\n** Warning: ** the algorithm did not terminate reliably!\n ",
if(x$ierr) "most probably because of collinear data"
else "(in the available number of iterations)", "\n")
}
invisible(x)
}
volume <- function(object, ...) UseMethod("volume")
if(FALSE) ## correct only for dimension d = 2 -- was used up to May 2019 :
volume.ellipsoid <- function(object) {
A <- object$cov
pi * object$d2 * sqrt(det(A))
}
## modified MM from a proposal by Keefe Murphy, e-mail 2019-05-15
volume.ellipsoid <- function(object, log=FALSE, ...) {
stopifnot((p <- length(object$loc)) >= 1)
lDet2 <- as.numeric(determinant(object$cov)$modulus) / 2 # = log(sqrt(det(.)))
lV <- p/2 * log(pi * object$d2) + lDet2 - lgamma(p/2 + 1)
if(log) lV else exp(lV)
}
## For p = 2 :
## Return (x[i],y[i]) points, i = 1:n, on boundary of ellipse, given
## by 2 x 2 matrix A[], origin 'loc' and d(xy, loc) ^2 = 'd2'
ellipsoidPoints <- function(A, d2, loc, n.half = 201)
{
if(length(d <- dim(A)) != 2 || (p <- d[1]) != d[2])
stop("'A' must be p x p cov-matrix defining an ellipsoid")
if(p == 2) {
detA <- A[1, 1] * A[2, 2] - A[1, 2]^2
yl2 <- A[2, 2] * d2 # = (y_max - y_loc)^2
y <- seq( - sqrt(yl2), sqrt(yl2), length = n.half)
sqrt.discr <- sqrt(detA * pmax(0, yl2 - y^2))/A[2, 2]
sqrt.discr[c(1, n.half)] <- 0
b <- loc[1] + A[1, 2]/A[2, 2] * y
y <- loc[2] + y
return(rbind(cbind( b - sqrt.discr, y),
cbind(rev(b + sqrt.discr), rev(y))))
} else { ## p >= 3
detA <- det(A)
##-- need something like polar coordinates
stop("ellipsoidPoints() not yet implemented for p >= 3 dim.")
}
}
predict.ellipsoid <- function(object, n.out = 201, ...)
ellipsoidPoints(object$cov, d2 = object$d2, loc= object$loc, n.half = n.out)
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.