I would like to randomly assign positive integers to G
groups, such that they sum up to V
.
For example, if G = 3
and V = 21
, valid results may be (7, 7, 7)
, (10, 6, 5)
, etc.
Is there a straightforward way to do this?
Editor's notice (from 李哲源):
If values are not restricted to integers, the problem is simple and has been addressed in Choosing n numbers with fixed sum.
For integers, there is a previous Q & A: Generate N random integers that sum to M in R but it appears more complicated and is hard to follow. The loop based solution over there is also not satisfying.
non-negative integers
Let
n
be sample size:is a
G x n
matrix, where each column is a multinomial sample that sums up toV
.By passing
rep.int(1 / G, G)
to argumentprob
I assume that each group has equal probability of "success".positive integers
As Gregor mentions, a multinomial sample can contain 0. If such samples are undesired, they should be rejected. As a result, we sample from a truncated multinomial distribution.
In How to generate target number of samples from a distribution under a rejection criterion I suggested an "over-sampling" approach to achieve "vectorization" for a truncated sampling. Simply put, Knowing the acceptance probability we can estimate the expected number of trials
M
to see the first "success" (non-zero). We first sample say1.25 * M
samples, then there will be at least one "success" in these samples. We randomly return one as the output.The following function implements this idea to generate truncated multinomial samples without 0.
Now let's try
Directly using
rmultinom
to draw samples can occasionally result in ones with 0:But there is no such issue by using
positive_rmultinom
:Probably a less expensive way, but this seems to work.
Not sure how to do with
runif