← Interactive tools

Random Variable Visualizer

An interactive take on the idea that a random variable is a quantity that fluctuates as its underlying randomness ω is resampled. Write a short, Excel-like program — X = Unif({1..6}), Y = Exp(3), Z = X + Y — and watch the values, empirical statistics, and animated Monte-Carlo plots update live. Absent any conditioning there is one shared ω per tick, so every variable is drawn together and coupling and independence come out exact and automatic. Events (True/False) and their probabilities are first-class, and conditioning a variable, (X | E), opens its own universe so the conditional can sit beside the unconditional.

New here? Pick an example from the preset menu in the toolbar (Monty Hall, the birthday paradox, …), watch it run, then edit the program and press Run. The language reference explains every piece.

A companion to Terence Tao's 2016 blog post “Visualising random variables”, whose animated-GIF illustrations this app makes interactive; several features were suggested by that post's commenters. Runs entirely in your browser. Coded with the assistance of Claude Code.

32
1024

Program


      
language cheat-sheet

Random variables and constants both use = (constants take a leading let); equality is ==; commands are plain words.

X = Unif({1..6})uniform on a set (dice)
U = Unif(0, 1)uniform on an interval
Y = Exp(3)exponential, rate 3
G = Normal(0, 1)Gaussian (mean, sd)
also Bernoulli(p), Binomial(n,p), Poisson(λ), Geometric(p)
Z = X + Yderived — stays coupled to X, Y
E = (X > 3)an event — True/False, with P(·)
C = Coin() · E and CBoolean(1/2); combine with and/or/not
let n = 100a constant (sizes, parameters)
V = Sample(Exp(1), n)n independent copies → a vector
M = AVERAGE(V)SUM, AVERAGE, MAX, MIN, STDEV, COUNT
condition on X^2+Y^2 <= 1reject states where it fails (global)
Y = (X | X > 3)condition one variable — its own universe
statistic Cov(X, Y)track an empirical statistic live
also Mean, SD, Var, Corr, Median, Q1, Q3, Percentile, Mode, Entropy, Max, Min
plot X · plot X, Ychoose what the right panel shows

Convention (not enforced): Capitalised names for random variables, lower-case for constants, UPPERCASE for functions.

Values (live)

variablevaluemean ± sd

Plot

40

Language reference

The app runs a small, Excel-like expression language. Each line is one statement, and # begins a comment. Everything listed here is supported today; this reference will grow as the language does.

The model — one shared ω

A random variable is stored as an expression over independent primitive draws, not as a fixed number. Every tick a single shared sample point ω is drawn and all primitives are resampled together (in the default universe — each conditioned universe has its own ω, below), so:

Z = X + Ystays coupled to X and Y (same ω)
W = X - Xis exactly 0, always
two separate drawsare independent automatically

Reusing a name refers to the same variable; writing a fresh Distribution(...) makes a new, independent one.

Conditioning a variable with (X | E) draws it in a separate universe — its own ω, resampled until E holds — so a conditional is independent of the original and of other universes (see the conditioning section below).

Assignments, constants & comments
Name = exprdefine a random variable (an event if expr is a comparison or boolean)
let name = exprdefine a constant — a fixed number, used for parameters and vector sizes
a == bequality test (gives 1 or 0); a single = is assignment
:=accepted as an alias for =
# …comment to the end of the line

A random variable is fixed by its definition and cannot be reassigned — in particular X = X + 1 is an error. (A random variable is a quantity, not a mutable cell of memory.)

Names that clash with a reserved word — a keyword, function, distribution, or constructor (e.g. Normal, SUM, and) — are rejected, so pick another. (Statistic names like P or Median are not reserved, since they live only inside the statistic command.)

Conventions (recommended, not enforced): Capitalised names for random variables, lower-case for constants, UPPERCASE for functions.

Distributions
Sets (for discrete uniforms)
{1..6}the integer range 1, 2, …, 6
{1, 2, 5, 10}an explicit set of values
Operators & comparisons
+   −   *   /   ^arithmetic (^ is power, also written **); unary minus too
<   <=   >   >=   ==   !=comparisons — each gives an event (see below)

Example: E = (X > 3) is an event, displayed True/False with its empirical probability; used in arithmetic it counts as 0/1, so (X>3) + (Y>3) is a running tally.

Events (True/False) & the Boolean coin

An event is a True/False random quantity — anything built from a comparison, a boolean combination, or the Boolean constructor. Events show in the Values panel as True/False with their empirical probability P(·), and coerce to 0/1 wherever a number is expected (so Mean(E) estimates P(E)).

Boolean(p = 1/2)a coin: True with probability p (aliases Coin, Flip, Toss, Bool, Chance)
E = X > 3name an event from a comparison
True · Falsethe constant events (always / never)

Combine events with boolean operators. Three interchangeable spellings: word operators (primary), symbols && || !, and Excel-style functions AND/OR/NOT/XOR (variadic, so AND(A, B, C); any nonzero value counts as True).

Example: H1 = Coin(), H2 = Coin(), both = H1 and H2 — then P(both) settles near 0.25, a picture of independence.

Conditioning a variable: (X | E) & universes

(X | E) reads “X given E” — a fresh copy of X drawn in the world where the event E holds. Unlike condition on (which filters every variable), (X | E) makes a new quantity in its own universe, so the conditioned copy can sit beside the original:

Y = (X | X > 3)X restricted to X > 3 — its own universe
P = (both | atLeastOne)an event given an event
(X | E and F) · ((X | E) | F)condition on several events

Quantities from different universes are independent draws and cannot be mixed: X + (X | E) is an error, and a 2-D plot A, B needs both in one universe. Same-universe quantities stay coupled, e.g. plot (X|E), (Y|E). Each plot shows its universe as a | E tag; the Values panel groups variables by universe.

Try it: X = Unif(0, 10), Y = (X | X > 3), then plot X and plot Y — the unconditioned spread beside the conditioned one.

Functions

Reductions (vector → scalar)

Elementwise maths

Logic

IF also has the word form if C then A else B. The boolean functions AND, OR, NOT, XOR live in the Events section above.

MAX and MIN also accept several scalar arguments, e.g. MAX(X, Y, 0).

Vectors & the central limit theorem
Sample(dist, n)a length-n vector of independent draws from dist (n is a constant)

Combine with a reduction to watch concentration in action:

let n = 100
S = (SUM(Sample(Unif(0,1), n)) − n/2) / SQRT(n/12)
plot Sa standardised sum → approaches a standard normal as n grows
Commands: plot & condition
plot X1-D view (fading dots + histogram)
plot X, Y2-D scatter (both variables must live in one universe)
several plot linesopen several plot windows at once (stacked)
condition on Erejection sampling: keep only the ticks where the event E holds. This is global — it conditions the shared ω for every variable, so dependence can appear (an independent square collapses into a disk). To condition just one variable instead, use (X | E) (see “Conditioning a variable” above).

plot takes variable names (name an expression first, e.g. Y = (X | X>3), then plot Y). Plotting an unknown name, a constant, or a vector reports an error rather than guessing.

If a condition is very unlikely, the app caps the number of tries per tick; the acceptance rate is shown under the Values panel.

Scope: this app conditions only on events (True/False). It does not implement the more advanced notion of conditioning on a random variable — the conditional expectation E[X | Y], which lives in a coarser σ-algebra, needs measure theory and cannot be built empirically — and it certainly does not attempt conditioning on arbitrary σ-algebras.

Empirical statistics (statistic / track)

Unlike functions (which turn random variables into random variables), a statistic turns the whole stream of samples into a single number. Declare one with statistic … (or track …) and its live empirical value appears in the Values panel. The argument can be any expression, e.g. statistic Mean(X*Y).

Two conveniences:

statistic Cov(X, Y | E)a trailing | E conditions the whole statistic — here it means Cov((X|E), (Y|E))
statistic Max(X) - Min(X)combine statistics (and numbers) with + − * / ^ and parentheses to make a new one (the range, here)

Statistics are their own kind of object — they only live inside statistic and never mix into ordinary expressions (a statistic depends on the whole history, not one draw). A compound statistic may span universes, since it just combines numbers.

Mean, SD, Var, Cov, Corr, P and Max/Min are exact over the whole run; the quantile, mode, and entropy statistics are estimated from the most recent few thousand samples. Names are case-insensitive and accept common aliases (average, variance, stdev, covariance, correlation, prob, …).

The plot panel & theory overlay

Controls: style (dots / histogram / both), fuzz (spreads coincident points so density shows), colours (highlight the current sample, or a continuous gradient trail), 1:1 aspect lock for 2-D, and theory. When theory is on and the plotted variable is a single primitive distribution, its exact pdf/pmf is drawn over the histogram; for derived variables it reads “unavailable” rather than guessing.

Out of scope (by design)

This is a small declarative language for describing probability, deliberately not a general-purpose (Turing-complete) programming language — readability for a student comes before raw expressive power. It does not attempt:

General-purpose programmingno loops, user-defined functions, recursion, or mutable variables — every line stays a readable declaration, not an algorithm.
Random matriceseigenvalue statistics (gap distributions, …) need complex numbers and their own machinery — a different tool.
Conditioning on a random variableonly conditioning on events is supported; the conditional expectation E[X | Y] (a coarser σ-algebra) needs measure theory and can't be built empirically.
3-D plotsviews are 1-D and 2-D only.
Theory curves for complex distributionsthe exact pdf/pmf overlay is drawn only for a single primitive distribution; derived variables (convolutions, ratios, …) show “unavailable” rather than a guess.

For any of these, reach for a full-powered environment — MATLAB, R, or NumPy/SciPy. This applet can only do so much, and aims to do a few things clearly rather than everything.