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

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


BTW, my function could be a little more efficient:  it can only possibly 
have lowlimit > highlimit on the first coordinate, so that test could 
come out of the loop.

Duncan Murdoch



On 2025-04-24 4:05 p.m., Duncan Murdoch wrote:
> 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