MULTIVARIATE_T

Overview

The MULTIVARIATE_T function computes the probability density function (PDF), cumulative distribution function (CDF), or draws random samples from a multivariate t-distribution. This distribution is a generalization of the univariate Student’s t-distribution to multiple dimensions and is commonly used in robust statistical inference, portfolio modeling, and Bayesian analysis where heavier tails are needed compared to the multivariate normal distribution.

The multivariate t-distribution is characterized by three parameters: a location vector \mu (the mean), a positive semidefinite shape matrix \Sigma (analogous to a covariance matrix), and the degrees of freedom \nu. When \nu \to \infty, the distribution converges to a multivariate normal distribution. Lower values of \nu produce heavier tails, making the distribution more robust to outliers.

This implementation uses the scipy.stats.multivariate_t class from SciPy, which provides efficient computation via scipy.stats. The source code is available in the SciPy GitHub repository.

The probability density function for a p-dimensional multivariate t-distribution is:

f(x) = \frac{\Gamma\left(\frac{\nu + p}{2}\right)}{\Gamma\left(\frac{\nu}{2}\right) \nu^{p/2} \pi^{p/2} |\Sigma|^{1/2}} \left[1 + \frac{1}{\nu}(x - \mu)^\top \Sigma^{-1} (x - \mu)\right]^{-(\nu + p)/2}

where \Gamma is the gamma function, \nu is the degrees of freedom (must be greater than zero), and |\Sigma| is the determinant of the shape matrix. The function supports three computation methods: pdf for probability density, cdf for cumulative probability, and rvs for generating random samples.

This example function is provided as-is without any representation of accuracy.

Excel Usage

=MULTIVARIATE_T(x, loc, shape, df, mvt_method, size)
  • x (list[list], optional, default: null): Points at which to evaluate the distribution. Each row is a point, each column is a dimension.
  • loc (list[list], optional, default: null): Location (mean) vector of the distribution as a column vector. Default is zero vector.
  • shape (list[list], optional, default: null): Positive semidefinite shape (covariance) matrix of the distribution. Default is identity matrix.
  • df (float, optional, default: 1): Degrees of freedom. Must be greater than zero.
  • mvt_method (str, optional, default: “pdf”): Computation method to use.
  • size (int, optional, default: null): Number of random samples to draw when method is rvs.

Returns (list[list]): 2D list of results, or error message string.

Examples

Example 1: PDF at origin with 2D standard t-distribution

Inputs:

x loc shape df mvt_method
0 0 0 1 0 2 pdf
0 0 1

Excel formula:

=MULTIVARIATE_T({0,0}, {0;0}, {1,0;0,1}, 2, "pdf")

Expected output:

Result
0.1592

Example 2: CDF at origin with 2D standard t-distribution

Inputs:

x loc shape df mvt_method
0 0 0 1 0 2 cdf
0 0 1

Excel formula:

=MULTIVARIATE_T({0,0}, {0;0}, {1,0;0,1}, 2, "cdf")

Expected output:

Result
0.25

Example 3: Draw random samples from 2D t-distribution

Inputs:

x loc shape df mvt_method size
0 0 0 1 0 2 rvs 2
0 0 1

Excel formula:

=MULTIVARIATE_T({0,0}, {0;0}, {1,0;0,1}, 2, "rvs", 2)

Expected output:

"non-error"

Example 4: PDF with default location and shape parameters

Inputs:

x mvt_method
1 1 pdf

Excel formula:

=MULTIVARIATE_T({1,1}, "pdf")

Expected output:

Result
0.03063

Python Code

import math
from scipy.stats import multivariate_t as scipy_multivariate_t

def multivariate_t(x=None, loc=None, shape=None, df=1, mvt_method='pdf', size=None):
    """
    Computes the PDF, CDF, or draws random samples from a multivariate t-distribution.

    See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.multivariate_t.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        x (list[list], optional): Points at which to evaluate the distribution. Each row is a point, each column is a dimension. Default is None.
        loc (list[list], optional): Location (mean) vector of the distribution as a column vector. Default is zero vector. Default is None.
        shape (list[list], optional): Positive semidefinite shape (covariance) matrix of the distribution. Default is identity matrix. Default is None.
        df (float, optional): Degrees of freedom. Must be greater than zero. Default is 1.
        mvt_method (str, optional): Computation method to use. Valid options: PDF, CDF, RVS. Default is 'pdf'.
        size (int, optional): Number of random samples to draw when method is rvs. Default is None.

    Returns:
        list[list]: 2D list of results, or error message string.
    """
    def to2d(val):
        return [[val]] if not isinstance(val, list) else val

    # Normalize x
    x = to2d(x)

    # Validate x
    if not isinstance(x, list) or not all(isinstance(row, list) and all(isinstance(val, (int, float)) for val in row) for row in x):
        return "Invalid input: x must be a 2D list of floats."
    if len(x) == 0 or len(x[0]) == 0:
        return "Invalid input: x must be a non-empty 2D list."
    dim = len(x[0])

    # Validate loc
    if loc is not None:
        loc = to2d(loc)
        if not (isinstance(loc, list) and all(isinstance(row, list) and len(row) == 1 and isinstance(row[0], (int, float)) for row in loc)):
            return "Invalid input: loc must be a 2D column vector (list of lists with one float each)."
        if len(loc) != dim:
            return "Invalid input: loc must have the same number of rows as columns in x."
        loc_vec = [row[0] for row in loc]
    else:
        loc_vec = [0.0] * dim

    # Validate shape
    if shape is not None:
        shape = to2d(shape)
        if not (isinstance(shape, list) and all(isinstance(row, list) and len(row) == dim and all(isinstance(val, (int, float)) for val in row) for row in shape)):
            return "Invalid input: shape must be a 2D list of floats with shape (dim, dim)."
        if len(shape) != dim:
            return "Invalid input: shape must have the same number of rows as columns in x."
        shape_mat = shape
    else:
        shape_mat = [[float(i == j) for j in range(dim)] for i in range(dim)]

    # Validate df
    try:
        df_val = float(df) if df is not None else 1.0
    except Exception:
        return "Invalid input: df must be a number."
    if df_val <= 0:
        return "Invalid input: df must be greater than zero."

    # Validate mvt_method
    valid_methods = {'pdf', 'cdf', 'rvs'}
    if mvt_method not in valid_methods:
        return f"Invalid input: mvt_method must be one of {sorted(valid_methods)}."

    # Validate size
    if mvt_method == 'rvs':
        if size is None:
            return "Invalid input: size must be specified for 'rvs' method."
        try:
            size_val = int(size)
        except Exception:
            return "Invalid input: size must be an integer."
        if size_val <= 0:
            return "Invalid input: size must be a positive integer."

    # Create distribution
    try:
        dist = scipy_multivariate_t(loc=loc_vec, shape=shape_mat, df=df_val)
    except Exception as e:
        return f"scipy.stats.multivariate_t error: {e}"

    # Compute result
    try:
        if mvt_method == 'pdf':
            result = [[float(dist.pdf(row))] for row in x]
        elif mvt_method == 'cdf':
            result = [[float(dist.cdf(row))] for row in x]
        elif mvt_method == 'rvs':
            samples = dist.rvs(size=size_val)
            # If samples is 1D, wrap as 2D list
            if dim == 1:
                result = [[float(val)] for val in samples]
            else:
                result = [[float(val) for val in row] for row in samples]
    except Exception as e:
        return f"scipy.stats.multivariate_t {mvt_method} error: {e}"

    # Check for invalid output values
    for row in result:
        for val in row:
            if isinstance(val, float) and (math.isnan(val) or math.isinf(val)):
                return "Invalid output: result contains NaN or infinite values."

    return result

Online Calculator