confidence_ellipse
confidence_ellipse(
data: pd.DataFrame,
x: str,
y: str,
z: Optional[str] = None,
group_by: Optional[str] = None,
conf_level: float = 0.95,
robust: bool = False,
distribution: Literal['normal', 'hotelling'] = 'normal',
)Coordinates of confidence ellipses or ellipsoids of raw data, optionally by group.
Computes points on the boundary of the confidence region of two (ellipse) or three (ellipsoid) variables at a given confidence level, from the classical or a robust estimate of their mean and covariance matrix, and a normal or Hotelling’s T-squared quantile.
Parameters
data : pandas.DataFrame-
Data containing the variables.
x : str-
Column of the x-axis variable.
y : str-
Column of the y-axis variable.
z : str = None-
Column of the z-axis variable. When given, an ellipsoid is computed instead of an ellipse.
group_by : str = None-
Categorical column defining groups. When given, one ellipse (ellipsoid) is computed for each group.
conf_level : float = 0.95-
Confidence level, strictly between 0 and 1.
robust : bool = False-
When
True, the mean and covariance matrix are estimated robustly with scikit-learn’sEllipticEnvelope(Minimum Covariance Determinant). If the robust fit fails, the classical estimates are used with a warning. distribution : str = 'normal'-
Distribution of the quantile scaling the region: the chi-square distribution (
'normal', for large samples) or Hotelling’s T-squared distribution ('hotelling', for small samples). See Notes.
Returns
: pandas.DataFrame-
Coordinates of the points, in columns
'x'and'y', plus'z'for an ellipsoid: 361 points around each ellipse, or a 50 by 50 grid of points on each ellipsoid. Withgroup_by, the group of each point is in a column named aftergroup_by.
Raises
: TypeError-
If
datais not a DataFrame orconf_levelis not a number. : ValueError-
If a column is missing, an argument is invalid, a group has fewer than three observations (four for an ellipsoid), or the covariance matrix contains missing values.
Notes
With \(\hat{\boldsymbol{\mu}}\) and \(\hat{\boldsymbol{\Sigma}} = \mathbf{V}
\boldsymbol{\Lambda} \mathbf{V}^\top\) the estimated mean and covariance matrix of the \(p\) variables (\(p = 2\) or 3) and \(c\) the quantile, the points are \(\hat{\boldsymbol{\mu}} + \mathbf{V} (c\boldsymbol{\Lambda})^{1/2} \mathbf{u}\), where \(\mathbf{u}\) runs over the unit circle (sphere). The quantile is \(c = \chi^2_{1-\alpha}(p)\) with distribution='normal', and \(c = \frac{p(n-1)}{n-p} F_{1-\alpha}(p, n-p)\) with distribution='hotelling', where \(n\) is the number of observations (of each group). Derivations are given on the Theory page of the documentation, https://christiangoueguel.com/pyEllipse/theory.html.
At least \(p + 1\) observations are required, so that the covariance matrix can be nonsingular and \(n - p > 0\). A singular covariance matrix, e.g. of collinear variables, gives a flat region: a line segment, or a flat ellipsoid.
The robust estimates come from EllipticEnvelope(support_fraction=0.9, random_state=42), i.e. the reweighted Minimum Covariance Determinant estimator computed with the FAST-MCD algorithm (Rousseeuw and Van Driessen, 1999) on 90% of the observations. The reweighted covariance matrix is made consistent at the normal distribution (Croux and Haesbroeck, 1999), as by scikit-learn >= 1.8, so that the robust and classical regions agree for normal data without outliers. Older versions of scikit-learn do not apply this factor, so pyEllipse applies it.
References
Croux, C. and Haesbroeck, G. (1999). Influence function and efficiency of the minimum covariance determinant scatter matrix estimator. Journal of Multivariate Analysis, 71(2), 161-190.
Rousseeuw, P. J. and Van Driessen, K. (1999). A fast algorithm for the minimum covariance determinant estimator. Technometrics, 41(3), 212-223.
Examples
>>> import numpy as np
>>> import pandas as pd
>>> from pyEllipse import confidence_ellipse
>>> rng = np.random.default_rng(0)
>>> df = pd.DataFrame(rng.standard_normal((60, 2)), columns=['u', 'v'])
>>> df['group'] = np.repeat(['A', 'B', 'C'], 20)
>>> ellipses = confidence_ellipse(df, x='u', y='v', group_by='group', distribution='hotelling')
>>> ellipses.shape
(1083, 3)
>>> ellipses['group'].unique().tolist()
['A', 'B', 'C']