Message Boards Message Boards

2
|
5595 Views
|
2 Replies
|
6 Total Likes
View groups...
Share
Share this post:

Method to generate k random partitions without Reap/Sow?

Posted 11 years ago
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"}}}
POSTED BY: David G
2 Replies
Posted 11 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 BY: William Rummler
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 then
The multitake could be something like this
With[{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}]]
POSTED BY: Todd Rowland
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract