MULTIVARIATE_NORMAL
Overview
The MULTIVARIATE_NORMAL
function computes the probability density function (PDF), cumulative distribution function (CDF), log-PDF, log-CDF, entropy, or draws random samples from a multivariate normal (Gaussian) distribution. This is useful for modeling joint distributions of multiple correlated variables in statistics, finance, engineering, and data science. The multivariate normal distribution generalizes the univariate normal distribution to higher dimensions, allowing for specification of a mean vector and covariance matrix:
where is a -dimensional vector, is the mean vector, and is the covariance matrix. For more details, see the scipy.stats.multivariate_normal documentation .
This wrapper exposes only the most commonly used parameters: x
, mean
, cov
, method
, and optionally size
for random sampling. Advanced options and numerical integration parameters are not supported. This example function is provided as-is without any representation of accuracy.
Usage
To use the function in Excel:
=MULTIVARIATE_NORMAL(x, mean, cov, [method], [size])
x
(2D list, required): Table of points at which to evaluate the function. Each row is a point, each column is a variable.mean
(2D column vector, required): Mean vector of the distribution. Must have the same number of rows as columns inx
.cov
(2D matrix, required): Covariance matrix of the distribution. Must be square with size equal to the number of variables.method
(string, optional, default=pdf
): Which method to compute:pdf
,cdf
,logpdf
,logcdf
,entropy
, orrvs
.size
(integer, optional): Number of samples to draw ifmethod
isrvs
.
The function returns a 2D list of results for each input point, or an error message (string) if the input is invalid. For rvs
, returns a 2D list of samples. For entropy
, returns the same entropy value for each input row.
Examples
Example 1: Basic PDF Calculation
Inputs:
x | mean | cov | method | ||||
---|---|---|---|---|---|---|---|
0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | ||
1.0 | 1.0 | 0.0 | 1.0 |
Excel formula:
=MULTIVARIATE_NORMAL({0,0;1,1}, {0;0}, {1,0;0,1})
Expected output:
Result |
---|
0.159 |
0.059 |
Example 2: CDF with Nonzero Mean
Inputs:
x | mean | cov | method | ||||
---|---|---|---|---|---|---|---|
0.0 | 0.0 | 1.0 | 1.0 | 1.0 | 0.0 | cdf | |
1.0 | 1.0 | 0.0 | 1.0 |
Excel formula:
=MULTIVARIATE_NORMAL({0,0;1,1}, {1;1}, {1,0;0,1}, "cdf")
Expected output:
Result |
---|
0.025 |
0.250 |
Example 3: Entropy Calculation
Inputs:
x | mean | cov | method | ||||
---|---|---|---|---|---|---|---|
0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | entropy | |
1.0 | 1.0 | 0.0 | 1.0 |
Excel formula:
=MULTIVARIATE_NORMAL({0,0;1,1}, {0;0}, {1,0;0,1}, "entropy")
Expected output:
Result |
---|
2.838 |
2.838 |
Example 4: Draw Random Samples
Inputs:
mean | cov | method | size | |||
---|---|---|---|---|---|---|
0.0 | 0.0 | 1.0 | 0.0 | rvs | 2 | |
0.0 | 1.0 |
Excel formula:
=MULTIVARIATE_NORMAL(, {0;0}, {1,0;0,1}, "rvs", 2)
Expected output:
Sample 1 | Sample 2 |
---|---|
(values will vary) | (values will vary) |
For rvs
, the output is a 2D list of two samples, each with two values. The actual values will vary each time the function is called.
Python Code
from scipy.stats import multivariate_normal as scipy_multivariate_normal
from typing import List, Optional, Union
def multivariate_normal(
x: List[List[float]],
mean: Optional[List[List[float]]] = None,
cov: Optional[List[List[float]]] = None,
method: str = 'pdf',
size: Optional[int] = None
) -> Union[List[List[Optional[float]]], str]:
"""
Computes the PDF, CDF, log-PDF, log-CDF, entropy, or draws random samples from a multivariate normal distribution.
Args:
x: 2D list of float values. Points at which to evaluate the function or fit the distribution.
mean: 2D list of float values (column vector). Mean of the distribution. Default is zero vector.
cov: 2D list of float values. Covariance matrix of the distribution. Default is identity matrix.
method: Which method to compute (str): 'pdf', 'cdf', 'logpdf', 'logcdf', 'entropy', 'rvs'. Default is 'pdf'.
size: Number of samples to draw if method is 'rvs'. Optional.
Returns:
2D list of results for each input point, or an error message (str) if input is invalid.
This example function is provided as-is without any representation of accuracy.
"""
# Validate x
if not isinstance(x, list) or not all(isinstance(row, list) 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."
n_dim = len(x[0])
# Validate mean
if mean is None:
mean_vec = [0.0] * n_dim
else:
if not isinstance(mean, list) or not all(isinstance(row, list) for row in mean):
return "Invalid input: mean must be a 2D list (column vector)."
if len(mean) != n_dim or any(len(row) != 1 for row in mean):
return "Invalid input: mean must be a column vector with same dimension as x."
try:
mean_vec = [float(row[0]) for row in mean]
except Exception:
return "Invalid input: mean must contain numeric values."
# Validate cov
if cov is None:
cov_mat = [[float(i == j) for j in range(n_dim)] for i in range(n_dim)]
else:
if not isinstance(cov, list) or len(cov) != n_dim or any(len(row) != n_dim for row in cov):
return "Invalid input: cov must be a square 2D list with shape (n_dim, n_dim)."
try:
cov_mat = [[float(val) for val in row] for row in cov]
except Exception:
return "Invalid input: cov must contain numeric values."
# Validate method
valid_methods = {'pdf', 'cdf', 'logpdf', 'logcdf', 'entropy', 'rvs'}
if method not in valid_methods:
return f"Invalid method: {method}. Must be one of {sorted(valid_methods)}."
# Validate size
if method == 'rvs':
if size is None:
return "Invalid input: size must be specified for method 'rvs'."
if not isinstance(size, int) or size <= 0:
return "Invalid input: size must be a positive integer."
# Try to create the distribution
try:
dist = scipy_multivariate_normal(mean=mean_vec, cov=cov_mat)
except Exception as e:
return f"scipy.multivariate_normal error: {e}"
# Compute result
try:
if method == 'pdf':
result = [[float(dist.pdf(row))] for row in x]
elif method == 'cdf':
result = [[float(dist.cdf(row))] for row in x]
elif method == 'logpdf':
result = [[float(dist.logpdf(row))] for row in x]
elif method == 'logcdf':
result = [[float(dist.logcdf(row))] for row in x]
elif method == 'entropy':
ent = float(dist.entropy())
result = [[ent] for _ in x]
elif method == 'rvs':
samples = dist.rvs(size=size)
# Ensure samples is 2D list
if n_dim == 1:
samples = [[float(s)] for s in samples]
else:
samples = [list(map(float, row)) for row in samples]
result = samples if size > 1 else [samples]
else:
return f"Invalid method: {method}."
except Exception as e:
return f"scipy.multivariate_normal error: {e}"
# Check for invalid values
import math
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 Inf."
return result