[R] Generate random vectors (continuous number) with a fixed sum

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Thu Apr 24 22:05:48 CEST 2025


On 2025-04-24 1:33 p.m., Brian Smith wrote:
> Hi Rui,
> 
> This code is able to generate absolutely correct random sample vector
> based on the applicable constraints.
> 
> I have one question though.
> 
> If I understood the R code correctly then, the first element is
> drawing random number from Uniform distribution unconditionally,
> however drawing of sample point for the second element is conditional
> to the first one. Therefore if we have large vector size instead of
> current 2, I guess the feasible region for the last few elements will
> be very small.
> 
> Will that be any problem? does there any algorithm exist where all
> (n-1) elements would be drawn unconditionally assuming our vector has
> n elements?

The answer could be yes or no depending on what you mean by "drawn 
unconditionally".

If you mean "draw a coordinate that depends on previous coordinate 
draws, and always accept it" then the answer is yes.  You would modify 
the limits of each draw depending on previous draws and the limits on 
upcoming draws.

If you mean "draw each coordinate independently of previous draws", then 
then answer is no, you can't do that except in a few very special cases.

Here's an example function:

rfixedsum <- function(n, sum, lower, upper) {
   dim <- length(lower)
   stopifnot(dim == length(upper), length(sum) == 1)

   result <- matrix(NA, n, dim)
   currentsums <- 0

   for (i in 1:(dim-1)) {
     # The highest following values could be is sum(upper[(i + 1):dim))
     # The lowest they could be is sum(lower[(i + 1):dim)
     lowlimit <- pmax(lower[i], sum - currentsums - sum(upper[(i + 1):dim]))
     highlimit <- pmin(upper[i], sum - currentsums - sum(lower[(i + 
1):dim]))
     if (any(lowlimit > highlimit))
       stop("sampling is impossible")
     newvals <- runif(n, lowlimit, highlimit)
     currentsums <- currentsums + newvals
     result[,i] <- newvals
   }
   result[, dim] <- sum - currentsums
   result
}


Duncan Murdoch



More information about the R-help mailing list