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