Method to generate k random partitions without Reap/Sow?

Posted 10 years ago
4960 Views
|
2 Replies
|
6 Total Likes
|
 Is there a method for sampling from a poplulation of n objects, without replacement, to generate k random partitions that doesn't use Reap/Sow?I want to sample from a poplulation of n objects, without replacement, to generate k random partitions (eg, in a Multinomial sense). So far, the only non-procedural methods I've come up with use Reap/Sow. Is it possible to do this without using Reap/Sow? I don't have a problem with using Reap/Sow. I'm only curious if that is the only way to implement this other than using a procedural method. There may even be a built-in command that does this?Here is an example of a functional implementation that I wrote that uses Reap/Sow: In[1]:= randomPartitionsFunctional[pop_List, partLength_Integer] :=  With[{samp = RandomSample[pop, partLength]},   DeleteCases[pop, Alternatives @@ Sow[samp]]   ]  In[2]:= randomPartitionsFunctional[pop_List,    partLengths_?(VectorQ[#1, NumericQ] &)] :=  Flatten[Reap[     Fold[randomPartitionsFunctional[#1, #2] &, pop, partLengths]],    2] /; Length[pop] == Total[partLengths]In[3]:= randomPartitionsFunctional[Range[15], {3, 2, 3, 3, 4}]Out[3]= {{15, 10, 9}, {14, 4}, {6, 1, 7}, {2, 12, 13}, {3, 11, 8, 5}}In[4]:= With[{pop = CharacterRange["a", "l"]}, randomPartitionsFunctional[pop, #] & /@   IntegerPartitions[Length[pop], {2}]]Out[4]= {{{"g", "l", "i", "a", "h", "c", "j", "d", "e", "f",    "b"}, {"k"}}, {{"b", "j", "e", "c", "d", "f", "g", "i", "k",    "h"}, {"l", "a"}}, {{"b", "j", "i", "l", "d", "k", "a", "e",    "h"}, {"c", "g", "f"}}, {{"d", "a", "k", "f", "i", "l", "g",    "b"}, {"h", "c", "e", "j"}}, {{"e", "f", "i", "c", "a", "j",    "b"}, {"d", "g", "k", "h", "l"}}, {{"e", "l", "c", "d", "f",    "a"}, {"h", "g", "k", "b", "i", "j"}}}
2 Replies
Sort By:
Posted 10 years ago
 It seems like this would do what you want: f[population_, partitionSizes_] :=  Most@   Fold[    With[{rest = Last@#},      Join[       Most@#,       Through@{Extract, Delete}[         rest, List /@ RandomSample[Range@Length@rest, #2]]]] &,    {population},   partitionSizes]population = Range@10;partitionSizes = RandomSample@RandomChoice@IntegerPartitions@Length@population(* Out: {4, 6} *)f[population, partitionSizes](* Out: {{3, 8, 5, 2}, {7, 1, 10, 9, 6, 4}} *)[Updated this to make it a bit tidier.]
Posted 10 years ago
 It seems like this task can be divided into three parts, taking a random sample, a choice of random sizes, and a way of taking from the random sample.Can you use RandomSampl and thenThe multitake could be something like thisWith[{list = Range[20]}, list[[# + 1 ;; #2]] & @@@   Partition[FoldList[Plus, 0, {3, 2, 3, 3, 4, 5}], 2, 1]]There are a number of ways to get the choice of random integer partition, depending on what would be a fair choice and whether n being large causes any practical concerns.For example if it is more fair at the sampling level you could just use Pick, e.g.,With[{list=Range[200], p=RandomInteger[{1,k},200]}, Table[Pick[list,p,i],{i,k}]]