Contents
Deep Breakdown
What it tells me (Situation Awareness): For a continuous bivariate distribution, the marginal PDF of X is obtained by integrating the joint PDF over all possible values of Y. This "integrates Y out", leaving only the behaviour of X. It is the continuous analogue of summing the rows of a discrete joint table. In DA/DS this is essential when working with multivariate Gaussian models, copulas, and Bayesian inference where you compute to get the marginal posterior.
Flowchart
Real-world use
Where it is used
You fit a bivariate distribution to two continuous features (e.g., age and spending) and want to analyse each feature's distribution individually, without conditioning on the other.
Problem it solves
After fitting a joint model, you often need the distribution of just one variable for reporting, simulation, or comparison. The marginal PDF extracts this without requiring a new fit.
How it solves the problem
Integrating over all Y values collapses the joint density into a univariate density. The resulting is a valid PDF that sums (integrates) to 1 and fully describes X's distribution on its own.
Example in a business
A DS fits a bivariate Gaussian to (session_duration, revenue). The marginal PDF of revenue is then used to set revenue threshold alerts and compute the probability that any given user session generates revenue above a target, marginalising over session duration.
The formula, piece by piece
| Symbol | Meaning |
|---|---|
| Marginal PDF of X at value x | |
| Integral over all possible values of Y | |
| Joint PDF | |
| Integration variable (Y is being "integrated out") |
Full formula:
The formula in words
"The marginal density of X at value x equals the integral of the joint density over all possible y values, with x held fixed." You are adding up all the joint density along the vertical slice at position x.
Critical Concepts
- Integrating out: the Y variable disappears after integration; only x remains.
- Valid PDF: and .
- Information loss: marginals do not recover the joint; the dependency structure is lost.
- Bivariate Gaussian marginals: each marginal of a bivariate Gaussian is itself Gaussian.
- Numerical integration: in practice, use
scipy.integrate.quador Monte Carlo integration when analytical form is unavailable.
Step-by-step calculation (tiny example)
Joint PDF: for , . Find marginal .
Step 1: Set up the integral over y
Step 2: Integrate
Step 3: Result for
Step 4: Verify normalisation
Code examples
Beginner example (Python)
import numpy as np
from scipy import integrate
# Joint PDF: f(x,y) = x + y on [0,1] x [0,1]
def joint_pdf(y: float, x: float) -> float:
return x + y
# Compute marginal f_X(x) numerically for several x values
x_grid = np.linspace(0, 1, 6)
for x_val in x_grid:
marginal, _ = integrate.quad(joint_pdf, 0, 1, args=(x_val,))
# Analytical: f_X(x) = x + 0.5
analytical = x_val + 0.5
print(f"x={x_val:.2f}: f_X(x) = {marginal:.4f} (analytical: {analytical:.4f})")Beginner example (R)
# Marginal f_X(x) = integrate f(x,y) dy from 0 to 1
joint_pdf <- function(y, x_val) x_val + y
x_grid <- seq(0, 1, by = 0.2)
for (x_val in x_grid) {
result <- integrate(joint_pdf, lower = 0, upper = 1, x_val = x_val)
cat(sprintf("x=%.1f: f_X(x) = %.4f (analytical: %.4f)\n", x_val, result$value, x_val + 0.5))
}Professional example (Python)
import numpy as np
from scipy import integrate
from scipy.stats import multivariate_normal
def bivariate_gaussian_marginal_x(
x_grid: np.ndarray,
mean: list[float],
cov: list[list[float]],
y_lower: float = -10.0,
y_upper: float = 10.0,
) -> np.ndarray:
# Compute marginal PDF of X by numerically integrating the bivariate Gaussian.
# For bivariate Gaussian, this recovers N(mean_x, sigma_x^2) analytically.
dist = multivariate_normal(mean=mean, cov=cov)
marginal_densities = np.zeros_like(x_grid, dtype=float)
for i, x_val in enumerate(x_grid):
def integrand(y: float) -> float:
return dist.pdf([x_val, y])
marginal_densities[i], _ = integrate.quad(integrand, y_lower, y_upper)
return marginal_densities
if __name__ == "__main__":
from scipy.stats import norm
MEAN = [5.0, 3.0]
COV = [[4.0, 1.5], [1.5, 2.0]]
x_vals = np.linspace(0, 10, 50)
numerical_marginal = bivariate_gaussian_marginal_x(x_vals, MEAN, COV)
analytical_marginal = norm.pdf(x_vals, loc=MEAN[0], scale=COV[0][0] ** 0.5)
max_error = np.max(np.abs(numerical_marginal - analytical_marginal))
print(f"Max absolute error (numerical vs analytical): {max_error:.2e}")
print("Numerical integration recovers the Gaussian marginal correctly.")Source: AIO p. 85`