Recommended Free Tools
scipy.stats.multivariate_normal handles four different jobs: evaluate density with pdf, compute cumulative probability with cdf, draw samples with rvs, and estimate parameters with fit. The examples below target the SciPy v1.18.0 API. The key shape rule is that the final axis of each point array contains the vector’s components.
What mean and covariance represent
A multivariate normal distribution describes a vector of related variables. Its mean is the location vector, and its cov describes variance in each component and covariance between components. For a two-component distribution, for example, the mean has shape (2,) and a full covariance matrix has shape (2, 2).
As an Amazon Associate I earn from qualifying purchases.
The SciPy v1.18.0 reference describes multivariate_normal as “A multivariate normal random variable.” Its API reference accepts covariance as a scalar (a multiple of the identity matrix), a vector of diagonal entries, a two-dimensional array, or a Covariance object. If mean is omitted, the mean is the zero vector.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →import numpy as np
from scipy.stats import multivariate_normal
mean = np.array([0.0, 1.0])
cov = np.array([[1.0, 0.4],
[0.4, 2.0]])
Choose direct calls or a frozen distribution
Use the module-level methods when parameters are supplied for an individual operation. Construct a frozen distribution when you will reuse the same mean and covariance; the object retains those parameters for subsequent calls.
#1 Best Overall
# Direct call: provide parameters to the method
value = multivariate_normal.pdf([0.5, 1.2], mean=mean, cov=cov)
# Frozen distribution: provide parameters once
rv = multivariate_normal(mean=mean, cov=cov)
value_again = rv.pdf([0.5, 1.2])
For both calls, the point has shape (2,): its final axis lists the two components.
Evaluate density with pdf and logpdf
pdf(x, mean=None, cov=1, allow_singular=False) evaluates the probability density at each point. It does not return the probability that a continuous random variable equals that exact point; a density is a value used to describe probability over regions.
The density is based on the distance from the mean under the covariance geometry. For a full-rank covariance matrix Σ, the documented expression uses its determinant and inverse:
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Rank #2
f(x) = 1 / sqrt((2π)^k det(Σ)) × exp(-1/2 (x − μ)ᵀΣ⁻¹(x − μ))
Here μ is the mean and k is the rank of Σ. For calculations where very small densities could underflow, use logpdf to obtain log density instead.
points = np.array([
[0.5, 1.2],
[1.0, 0.0],
]) # shape (n, d): two points, two components each
densities = rv.pdf(points) # shape (2,)
log_densities = rv.logpdf(points) # shape (2,)
More generally, x may have shape (d,) for one point, (n, d) for a batch, or (..., d) for a grid or higher-dimensional batch. In every case the final dimension d identifies components; preceding dimensions identify points.
Compute cumulative probability with cdf
cdf(x, mean=None, cov=1, allow_singular=False, maxpts=1000000*dim, abseps=1e-5, releps=1e-5, lower_limit=None) computes cumulative probability up to the supplied upper point. For a multivariate distribution, this concerns a rectangular region, not a one-dimensional interval.
Free tools Windows power users keep installed
One-click scans. No signup required.
For example, the following requests the probability that both components are at most the corresponding upper limits. The vector’s final axis contains the two component bounds.
upper = np.array([1.0, 2.0]) # shape (d,)
p = rv.cdf(upper)
To calculate probability within a rectangular box, provide its lower and upper corners. The optional lower_limit defines the lower corner; the x argument remains the upper corner.
lower = np.array([-1.0, 0.0])
upper = np.array([1.0, 2.0])
p_box = rv.cdf(upper, lower_limit=lower)
The CDF API exposes maxpts, abseps, and releps to control the numerical integration work budget and error tolerances. Increase the point budget or tighten tolerances when the calculation’s accuracy requirements call for it, recognizing that the work and runtime may increase. The result is a numerical CDF calculation, so do not treat the tolerances as a guarantee that every problem reaches those errors.
Generate random draws with rvs
rvs(mean=None, cov=1, size=1, random_state=None) draws random vectors. When using a frozen object, its parameters are already set; specify the number of draws with size. For repeatable results, pass an explicitly seeded random generator and keep or recreate its state as intended.
rng = np.random.default_rng(42)
samples = rv.rvs(size=5, random_state=rng)
# For a two-component distribution, samples has shape (5, 2).
The constructor also accepts a seed argument, which may be None, an integer, a RandomState, or a Generator. Reproducibility depends on using the same seed and state progression: reusing an already-advanced generator does not restart its sequence.
Best Value
Fit parameters with fit
The SciPy v1.18.0 reference lists fit(x, fix_mean=None, fix_cov=None), but that signature alone does not specify the data orientation, estimator, return structure, or precise behavior of fixed parameters. Because those details determine whether a fit is correct, do not infer them from the similarly named univariate fitting API or assume a particular shape or return value without checking the targeted release’s implementation and documentation.
Before relying on fit, consult the version-specific SciPy multivariate-normal reference and confirm those details for the installed release. This article therefore does not present a fitting code example that would imply unverified orientation or output behavior.
Check covariance validity and singular cases
For an ordinary array covariance, allow_singular=False is the default and the covariance must be strictly positive definite. Set allow_singular=True only when a positive-semidefinite covariance is intentionally rank-deficient; SciPy then uses a pseudo-inverse and pseudo-determinant for the degenerate case.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWith array input, SciPy does not check covariance symmetry and uses only its lower-triangular portion. Supply a genuinely symmetric covariance matrix rather than relying on the function to validate or repair it. If cov is a Covariance object, allow_singular is ignored.
# Example of an intentionally rank-deficient covariance:
singular_cov = np.array([[1.0, 1.0],
[1.0, 1.0]])
rv_singular = multivariate_normal(
mean=[0.0, 0.0],
cov=singular_cov,
allow_singular=True,
)
A singular covariance describes a distribution confined to a lower-dimensional subspace, rather than an ordinary full-dimensional density. SciPy documents an extension of the density definition for this case; consult its reference for the degenerate-case treatment.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




