Skip to content

bivariate_quantiles module

Bivariate vector quantiles and ranks.

This module implements the bivariate case of the vector quantiles and vector ranks construction of Chernozhukov, Galichon, Hallin, and Henry (2017).

The main workflow is:

  1. Solve for the dual weights v with :func:_solve_for_v.
  2. Evaluate quantiles with :func:bivariate_quantiles_v or :func:bivariate_quantiles.
  3. Read off barycentric ranks with :func:bivariate_ranks.
References

Chernozhukov, Galichon, Hallin, and Henry. "Monge-Kantorovich Depth, Quantiles, Ranks and Signs." Annals of Statistics 45(1), 2017.

bivariate_quantiles(y, tau, n_nodes=32, verbose=False)

Solve for the dual weights and evaluate bivariate quantiles.

Parameters:

Name Type Description Default
y ndarray

Observations with shape (n, 2).

required
tau ndarray

Query points in [0, 1]^2 with shape (m, 2).

required
n_nodes int

Number of Chebyshev nodes for the quadrature.

32
verbose bool

Print optimisation diagnostics when True.

False

Returns:

Type Description
ndarray

Bivariate quantiles evaluated at tau.

Source code in bs_python_utils/stats/bivariate_quantiles.py
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
def bivariate_quantiles(
    y: np.ndarray, tau: np.ndarray, n_nodes: int = 32, verbose: bool = False
) -> np.ndarray:
    """Solve for the dual weights and evaluate bivariate quantiles.

    Args:
        y: Observations with shape ``(n, 2)``.
        tau: Query points in ``[0, 1]^2`` with shape ``(m, 2)``.
        n_nodes: Number of Chebyshev nodes for the quadrature.
        verbose: Print optimisation diagnostics when ``True``.

    Returns:
        Bivariate quantiles evaluated at ``tau``.
    """
    v, _ = _solve_for_v(y, n_nodes, verbose)
    return bivariate_quantiles_v(y, tau, v)

bivariate_quantiles_v(y, tau, v)

Evaluate vector quantiles for fixed dual weights.

Parameters:

Name Type Description Default
y ndarray

Observations with shape (n, 2).

required
tau ndarray

Evaluation points in [0, 1]^2 with shape (m, 2).

required
v ndarray

Dual weights solving the optimal transport problem, with length n.

required

Returns:

Type Description
ndarray

Array of quantile locations with shape (m, 2).

Raises:

Type Description
SystemExit

If tau does not have exactly two columns.

Source code in bs_python_utils/stats/bivariate_quantiles.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
def bivariate_quantiles_v(y: np.ndarray, tau: np.ndarray, v: np.ndarray) -> np.ndarray:
    """Evaluate vector quantiles for fixed dual weights.

    Args:
        y: Observations with shape ``(n, 2)``.
        tau: Evaluation points in ``[0, 1]^2`` with shape ``(m, 2)``.
        v: Dual weights solving the optimal transport problem, with length
            ``n``.

    Returns:
        Array of quantile locations with shape ``(m, 2)``.

    Raises:
        SystemExit: If ``tau`` does not have exactly two columns.
    """
    if tau.shape[1] != 2:
        bs_error_abort("tau must have two columns")
    q = y[np.argmax(tau @ y.T - v, axis=1), :]
    return cast(np.ndarray, q)

bivariate_ranks(y, n_nodes=32, verbose=False)

Compute barycentric ranks for each observation.

Parameters:

Name Type Description Default
y ndarray

Observations with shape (n, 2).

required
n_nodes int

Number of Chebyshev nodes used in the quadrature.

32
verbose bool

Print diagnostics when True.

False

Returns:

Type Description
ndarray

Array of average ranks (shape (n, 2)) with nan for zero-mass cells.

Source code in bs_python_utils/stats/bivariate_quantiles.py
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
def bivariate_ranks(
    y: np.ndarray,
    n_nodes: int = 32,
    verbose: bool = False,
) -> np.ndarray:
    """Compute barycentric ranks for each observation.

    Args:
        y: Observations with shape ``(n, 2)``.
        n_nodes: Number of Chebyshev nodes used in the quadrature.
        verbose: Print diagnostics when ``True``.

    Returns:
        Array of average ranks (shape ``(n, 2)``) with ``nan`` for zero-mass cells.
    """
    d = y.shape[1]

    if d != 2:
        bs_error_abort(f"only works for 2-dimensional y, not for {d}")

    _, bivranks = _solve_for_v(y, n_nodes, verbose)
    return cast(np.ndarray, bivranks)