1
$\begingroup$

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$.

$\endgroup$
4
  • 1
    $\begingroup$ Look up Differences and RandomChoice (with weights). $\endgroup$
    – Szabolcs
    Commented Feb 10, 2018 at 15:47
  • $\begingroup$ Ok RandomChoice, I think that will work. $\endgroup$
    – apg
    Commented Feb 10, 2018 at 15:49
  • $\begingroup$ Never use an upper-case letter for a variable as it will conflict with Mathematica's internal names. $\endgroup$ Commented Feb 10, 2018 at 17:29
  • $\begingroup$ 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. $\endgroup$
    – JimB
    Commented Feb 10, 2018 at 19:35

1 Answer 1

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

RandomChoice

SeedRandom[1]
rc = RandomChoice[binlengths -> Range[4], 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[1]
rved = RandomVariate[EmpiricalDistribution[WeightedData[Range[4], 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[[1]], #} &, #] &@(# <= 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[1]
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

$\endgroup$
1
  • $\begingroup$ Thank you, that is a big help. $\endgroup$
    – apg
    Commented Mar 6, 2018 at 12:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.