# Probability distribution defined by partitioning an interval

I am trying to efficiently sample from a known probability distribution.

If I have the interval $I=[0,m]$, and consider a partition on $I$ consisting of $n$ bins, how do I then uniformly draw a random variable $X$ which has the value $X \in \{1,2,\dots,n\}$ with probability given by the widths of the corresponding bin?

I have been drawing a uniform variate between $0$ and $m$, and then determining which bin it is in, but this quite is slow for large $n$.

• Look up Differences and RandomChoice (with weights). – Szabolcs Feb 10 '18 at 15:47
• Ok RandomChoice, I think that will work. – Alexander Kartun-Giles Feb 10 '18 at 15:49
• Never use an upper-case letter for a variable as it will conflict with Mathematica's internal names. – David G. Stork Feb 10 '18 at 17:29
• You want to "draw a random sample from a random variable $X$" rather than "uniformly draw a random variable $X$" as "uniformly" implies that the bin widths are all equal. – JimB Feb 10 '18 at 19:35

m = 20;
n = 4;
binlims = {0, 2, 9, 14, 20};
binlengths = Differences[binlims];


## RandomChoice

SeedRandom
rc = RandomChoice[binlengths -> Range, 20]


{4, 2, 4, 2, 2, 1, 3, 2, 2, 4, 2, 4, 2, 2, 4, 4, 4, 3, 2, 2}

## WeightedData + EmpiricalDistribution + RandomVariate

SeedRandom
rved = RandomVariate[EmpiricalDistribution[WeightedData[Range, binlengths]], 20]


{4, 2, 4, 2, 2, 1, 3, 2, 2, 4, 2, 4, 2, 2, 4, 4, 4, 3, 2, 2}

## UniformDistribution + TransformedDistribution + RandomVariate

This mimics the description of the process used to generate the random variable X, but it is much slower than the previous two methods.

ClearAll[pw]
pw[x_] := Piecewise[MapIndexed[{#2[], #} &, #] &@(# <= x < #2 & @@@
Partition[binlims, 2, 1])];

pw[x]


$\begin{cases} 1 & 0\leq x<2 \\ 2 & 2\leq x<9 \\ 3 & 9\leq x<14 \\ 4 & 14\leq x<20 \end{cases}$

SeedRandom
rvtd = RandomVariate[TransformedDistribution[pw[x],
Distributed[x, UniformDistribution[{0, m}]]], 20]


{4, 2, 4, 2, 2, 1, 3, 2, 2, 4, 2, 4, 2, 2, 4, 4, 4, 3, 2, 2}

When used with the same RandomSeed all three methods give the same result. The first two are roughly equal in terms of speed.

rc == rved  == rvtd


True