I think I have a solution that requires two functions: cov.rob from the MASS package and ellipsoidhull from the cluster package. cov.rob(xy, quantile.used = 50, method = "mve") finds about the "best" 50 points out of a total of 2d points in xy that are contained in an ellipse of minimal size. However, cov.rob does not directly return this ellipse, but rather some other ellipse estimated from the best points (the goal is to reliably estimate the covariance matrix). To find the minimum ellipse of the actual, we can give the best ellipsoidhull points that find the minimum ellipse, and we can use predict.ellipse to infer the coordinates of the path that defines the shell of the ellipse.
I am not 100% sure that this method is the simplest and / or 100% working (it seems that the second step of using ellipsoidhull can be avoided, but I did not understand how to do this.). It seems to at least work on my toy example ...
Suffice it to say, here is the code:
library(MASS) library(cluster)

Looks good! You can also view the ellipse object for more information.
best_ellipse
Here is a handy feature that adds an ellipse to an existing base graphic:
plot_min_ellipse <- function(xy, points_in_ellipse, color = "blue") { fit <- cov.rob(xy, quantile.used = points_in_ellipse, method = "mve") best_ellipse <- ellipsoidhull( xy[fit$best,] ) lines(predict(best_ellipse), col=color) }
Use it for more points:
x <- runif(100) y <- runif(100) xy <- cbind(x, y) plot(xy) plot_min_ellipse(xy, points_in_ellipse = 50)

source share