Reply to
- To: mathgroup at smc.vnet.net
- Subject: [mg23538] Reply to [mg23530]
- From: "Johannes Ludsteck" <ludsteck at zew.de>
- Date: Sat, 20 May 2000 03:10:17 -0400 (EDT)
- Organization: Zentr. f. Europ. Wirtschaftsforsch
- Sender: owner-wri-mathgroup at wolfram.com
Dear Wagner,
The solution to you problem is simple if you use Mathematica's
standard AddOn Packages, for example
<<Statistics`MultiDiscreteStatistics`
md=MultinomialDistribution[1,{0.2,0.4,0.1,0.3}]
Random[md]
{0,1,0,0}
N[Apply[Plus, RandomArray[md, 1000]]/1000]
{0.209, 0.398, 0.084, 0.309}
shows that you get the desired probabilities.
Therefore you get an index drawn from the above distribution by
typing.
Flatten[Position[Random[md], 1]]
If you need many repeated draws, you should use RandomArray for
efficiency reasons. For example, the following code makes 15
draws:
Flatten[Map[Position[#, 1] &, RandomArray[md, 15]]]
{3, 4, 4, 1, 2, 2, 2, 4, 3, 2, 2, 4, 4, 2, 4}
If you are interested in the algorithm used in the Mathematica
Package, just search for <Random[MultinomialDistribution> in the
code of the Package.
The code there seems at least to be shorter than the code in your
Module.
If you need a <very> fast implementation, you can speed up this
function by substituting the call to Random[BinomialDistribution...
inside of Random[MultinomialDistribution] by the code you find
there.
Hope that helps,
Johannes
> Howdy everyone,
>
> I have a list of probabilities (whose sum is 1.0), each associated
> with an index. I'd like to randomly choose an index based on
those
> probabilities. For example, suppose
>
> m = {0.2, 0.4, 0.1, 0.3}
>
> which dictates that index 1 should be selected with prob 0.2,
index 2
> with prob 0.4, index 3 with prob 0.1, and index 4 with prob 0.3.
>
> I've already written a function that works, but I think there should
> be a simpler, more elegant, and more efficient way of
accomplishing
> this task.
>
> Here's my solution:
>
> randomIndexPick[ m_ ] :=
> Module[ { r, s },
> r = Random[];
> s = Sort[ Thread[ { m, Range[ Length[m] ] } ] ];
> s = Table[ { Sum[ s[[i, 1]], { i, 1, k } ], s[[k, 2]] },
> { k, 1, Length[m] } ];
> s = Map[ ( { r ¾ First[#], Last[#] } ) &, s ];
> s = Select[ s, ( First[#] ) & ];
> Return[ s[[1, 2]] ] ];
>
> Table[ randomIndexPick[ {0.2, 0.4, 0.1, 0.3} ], {20} ]
>
> {4, 4, 1, 2, 2, 4, 4, 1, 4, 4, 2, 3, 1, 2, 2, 2, 4, 3, 2, 3}
>
> Does anybody have a better solution?
>
> Thanks!
> Wagner
Johannes Ludsteck
Centre for European Economic Research (ZEW)
Department of Labour Economics,
Human Resources and Social Policy
Phone (+49)(0)621/1235-157
Fax (+49)(0)621/1235-225
P.O.Box 103443
D-68034 Mannheim
GERMANY
Email: ludsteck at zew.de