Brian Smith
2025-Apr-22 16:50 UTC
[R] Generate random vectors (continuous number) with a fixed sum
Hi Rui, Thanks for the explanation. But in this case, are we looking at the correct solution at all? My goal is to generate random vector where: 1) the first element is bounded by (a[1], b[1]) and second element is bounded by (a[2], b[2]) 2) sum of the element is s According to the outcome, The first matrix values are bounded by c(a[1], b[1]) & second matrix values are bounded by c(a[2], b[2]) But, regarding the sum, I think we should have sum (element-wise) sum should be equal to s = 0.05528650577311. How could we achieve that then? On Tue, 22 Apr 2025 at 22:03, Rui Barradas <ruipbarradas at sapo.pt> wrote:> > ?s 12:39 de 22/04/2025, Brian Smith escreveu: > > Hi Rui, > > > > Many thanks for your time and insight. > > > > However, I am not sure if I could understand the code. Below is what I > > tried based on your code > > > > library(Surrogate) > > a <- c(0.015, 0.005) > > b <- c(0.070, 0.045) > > set.seed(2025) > > res <- mapply(\(a, b, s, n, m) RandVec(a, b, s, n, m), > > MoreArgs = list(s = 0.05528650577311, n = 2, m = 10000), a, b) > > > > res1 = res[[1]] > > res2 = res[[2]] > > > > apply(res1, 1, min) > a ## [1] TRUE TRUE > > apply(res2, 1, min) > a ## [1] FALSE TRUE > > > > I could not understand what basically 2 blocks of res signify? Which > > one I should take as final simulation of the vector? If I take the > > first block then the lower bound condition is fulfilled, but not with > > the second block. However with the both blocks, the total equals s is > > satisfying. > > > > I appreciate your further insight. > > > > Thanks and regards, > > > > On Mon, 21 Apr 2025 at 20:43, Rui Barradas <ruipbarradas at sapo.pt> wrote: > >> > >> Hello, > >> > >> Inline. > >> > >> ?s 16:08 de 21/04/2025, Rui Barradas escreveu: > >>> ?s 15:27 de 21/04/2025, Brian Smith escreveu: > >>>> Hi, > >>>> > >>>> There is a function called RandVec in the package Surrogate which can > >>>> generate andom vectors (continuous number) with a fixed sum > >>>> > >>>> The help page of this function states that: > >>>> > >>>> a > >>>> > >>>> The function RandVec generates an n by m matrix x. Each of the m > >>>> columns contain n random values lying in the interval [a,b]. The > >>>> argument a specifies the lower limit of the interval. Default 0. > >>>> > >>>> b > >>>> > >>>> The argument b specifies the upper limit of the interval. Default 1. > >>>> > >>>> However in my case, the lower and upper limits are not same. For > >>>> example, if I need to draw a pair of number x, y, such that x + y = 1, > >>>> then the lower and upper limits are different. > >>>> > >>>> I tried with below code > >>>> > >>>> library(Surrogate) > >>>> > >>>> RandVec(a=c(0.1, 0.2), b=c(0.2, 0.8), s=1, n=2, m=5)$RandVecOutput > >>>> > >>>> This generates error with message > >>>> > >>>> Error in if (b - a == 0) { : the condition has length > 1 > >>>> > >>>> Is there any way to generate the numbers with different lower and > >>>> upper limits? > >>>> > >>>> ______________________________________________ > >>>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > >>>> https://stat.ethz.ch/mailman/listinfo/r-help > >>>> PLEASE do read the posting guide https://www.R-project.org/posting- > >>>> guide.html > >>>> and provide commented, minimal, self-contained, reproducible code. > >>> Hello, > >>> > >>> Use ?mapply to cycle through all values of a and b. > >>> Note that the output matrices are transposed, the random vectors are the > >>> rows. > >> Sorry, this is not true. The columns are the random vectors, as > >> documented. An example setting the RNG seed, for reproducibility. > >> > >> > >> library(Surrogate) > >> > >> a <- c(0.1, 0.2) > >> b <- c(0.2, 0.8) > >> set.seed(2025) > >> res <- mapply(\(a, b, s, n, m) RandVec(a, b, s, n, m), > >> MoreArgs = list(s = 1, n = 2, m = 5), a, b) > >> > >> res > >> #> $RandVecOutput > >> #> [,1] [,2] [,3] [,4] [,5] > >> #> [1,] 0.146079 0.1649319 0.1413759 0.257086 0.1715478 > >> #> [2,] 0.253921 0.2350681 0.2586241 0.142914 0.2284522 > >> #> > >> #> $RandVecOutput > >> #> [,1] [,2] [,3] [,4] [,5] > >> #> [1,] 0.5930918 0.2154583 0.6915523 0.7167089 0.3617918 > >> #> [2,] 0.4069082 0.7845417 0.3084477 0.2832911 0.6382082 > >> > >> lapply(res, colSums) > >> #> $RandVecOutput > >> #> [1] 0.4 0.4 0.4 0.4 0.4 > >> #> > >> #> $RandVecOutput > >> #> [1] 1 1 1 1 1 > >> > >> > >> Hope this helps, > >> > >> Rui Barradas > >>> > >>> > >>> library(Surrogate) > >>> > >>> a <- c(0.1, 0.2) > >>> b <- c(0.2, 0.8) > >>> mapply(\(a, b, s, n, m) RandVec(a, b, s, n, m), > >>> MoreArgs = list(s = 1, n = 2, m = 5), a, b) > >>> #> $RandVecOutput > >>> #> [,1] [,2] [,3] [,4] [,5] > >>> #> [1,] 0.2004363 0.1552328 0.2391742 0.1744857 0.1949236 > >>> #> [2,] 0.1995637 0.2447672 0.1608258 0.2255143 0.2050764 > >>> #> > >>> #> $RandVecOutput > >>> #> [,1] [,2] [,3] [,4] [,5] > >>> #> [1,] 0.2157416 0.4691191 0.5067447 0.7749258 0.7728955 > >>> #> [2,] 0.7842584 0.5308809 0.4932553 0.2250742 0.2271045 > >>> > >>> > >>> Hope this helps, > >>> > >>> Rui Barradas > >>> > >>> > >> > >> > >> -- > >> Este e-mail foi analisado pelo software antiv?rus AVG para verificar a presen?a de v?rus. > >> www.avg.com > Hello, > > The two blocks of res are the two random matrices, one for each > combination of (a,b). mapply passes each of the values in its arguments > list (the ellipses in the help page) and computes the anonymous function > with the pairs (a[1], b[1]), (a[2], b[2]). > > Since a and b are two elements vectors the output res is a two members > named list. Your error is to compare the result of apply(res2, 1, min) > to a, when you should compare to a[2]. See the code below. > > > library(Surrogate) > a <- c(0.015, 0.005) > b <- c(0.070, 0.045) > set.seed(2025) > res <- mapply(\(a, b, s, n, m) RandVec(a, b, s, n, m), > MoreArgs = list(s = 0.05528650577311, n = 2, m = 10000), > a, b) > > res1 = res[[1]] > res2 = res[[2]] > > # first check that the sums are correct > # these sums should be s = 0.05528650577311, up to floating-point accuracy > lapply(res, \(x) colSums(x[, 1:5]) |> print(digits = 14L)) > #> [1] 0.05528650577311 0.05528650577311 0.05528650577311 0.05528650577311 > #> [5] 0.05528650577311 > #> [1] 0.05528650577311 0.05528650577311 0.05528650577311 0.05528650577311 > #> [5] 0.05528650577311 > #> $RandVecOutput > #> [1] 0.05528651 0.05528651 0.05528651 0.05528651 0.05528651 > #> > #> $RandVecOutput > #> [1] 0.05528651 0.05528651 0.05528651 0.05528651 0.05528651 > > # now check the min and max > apply(res1, 1, min) > a[1L] ## [1] TRUE TRUE > #> [1] TRUE TRUE > apply(res2, 1, min) > a[2L] ## [1] TRUE TRUE > #> [1] TRUE TRUE > > apply(res1, 1, max) < b[1L] ## [1] TRUE TRUE > #> [1] TRUE TRUE > apply(res2, 1, max) < b[2L] ## [1] TRUE TRUE > #> [1] TRUE TRUE > > > > Which one should you take as final simulation of the vector? Both. > The first matrix values are bounded by c(a[1], b[1]) with column sums > equal to s. > The second matrix values are bounded by c(a[2], b[2]) with column sums > also equal to s. > > Hoep this helps, > > Rui Barradas >
Brian Smith
2025-Apr-22 16:55 UTC
[R] Generate random vectors (continuous number) with a fixed sum
i.e. we should have
all elements of Reduce("+", res) should be equal to s =
0.05528650577311
My assertion is that it is not happing here.
On Tue, 22 Apr 2025 at 22:20, Brian Smith <briansmith199312 at gmail.com>
wrote:>
> Hi Rui,
>
> Thanks for the explanation.
>
> But in this case, are we looking at the correct solution at all?
>
> My goal is to generate random vector where:
> 1) the first element is bounded by (a[1], b[1]) and second element is
> bounded by (a[2], b[2])
> 2) sum of the element is s
>
> According to the outcome,
> The first matrix values are bounded by c(a[1], b[1]) & second matrix
> values are bounded by c(a[2], b[2])
>
> But,
> regarding the sum, I think we should have sum (element-wise) sum
> should be equal to s = 0.05528650577311.
>
> How could we achieve that then?
>
> On Tue, 22 Apr 2025 at 22:03, Rui Barradas <ruipbarradas at sapo.pt>
wrote:
> >
> > ?s 12:39 de 22/04/2025, Brian Smith escreveu:
> > > Hi Rui,
> > >
> > > Many thanks for your time and insight.
> > >
> > > However, I am not sure if I could understand the code. Below is
what I
> > > tried based on your code
> > >
> > > library(Surrogate)
> > > a <- c(0.015, 0.005)
> > > b <- c(0.070, 0.045)
> > > set.seed(2025)
> > > res <- mapply(\(a, b, s, n, m) RandVec(a, b, s, n, m),
> > > MoreArgs = list(s = 0.05528650577311, n = 2, m =
10000), a, b)
> > >
> > > res1 = res[[1]]
> > > res2 = res[[2]]
> > >
> > > apply(res1, 1, min) > a ## [1] TRUE TRUE
> > > apply(res2, 1, min) > a ## [1] FALSE TRUE
> > >
> > > I could not understand what basically 2 blocks of res signify?
Which
> > > one I should take as final simulation of the vector? If I take
the
> > > first block then the lower bound condition is fulfilled, but not
with
> > > the second block. However with the both blocks, the total equals
s is
> > > satisfying.
> > >
> > > I appreciate your further insight.
> > >
> > > Thanks and regards,
> > >
> > > On Mon, 21 Apr 2025 at 20:43, Rui Barradas <ruipbarradas at
sapo.pt> wrote:
> > >>
> > >> Hello,
> > >>
> > >> Inline.
> > >>
> > >> ?s 16:08 de 21/04/2025, Rui Barradas escreveu:
> > >>> ?s 15:27 de 21/04/2025, Brian Smith escreveu:
> > >>>> Hi,
> > >>>>
> > >>>> There is a function called RandVec in the package
Surrogate which can
> > >>>> generate andom vectors (continuous number) with a
fixed sum
> > >>>>
> > >>>> The help page of this function states that:
> > >>>>
> > >>>> a
> > >>>>
> > >>>> The function RandVec generates an n by m matrix x.
Each of the m
> > >>>> columns contain n random values lying in the interval
[a,b]. The
> > >>>> argument a specifies the lower limit of the interval.
Default 0.
> > >>>>
> > >>>> b
> > >>>>
> > >>>> The argument b specifies the upper limit of the
interval. Default 1.
> > >>>>
> > >>>> However in my case, the lower and upper limits are
not same. For
> > >>>> example, if I need to draw a pair of number x, y,
such that x + y = 1,
> > >>>> then the lower and upper limits are different.
> > >>>>
> > >>>> I tried with below code
> > >>>>
> > >>>> library(Surrogate)
> > >>>>
> > >>>> RandVec(a=c(0.1, 0.2), b=c(0.2, 0.8), s=1, n=2,
m=5)$RandVecOutput
> > >>>>
> > >>>> This generates error with message
> > >>>>
> > >>>> Error in if (b - a == 0) { : the condition has length
> 1
> > >>>>
> > >>>> Is there any way to generate the numbers with
different lower and
> > >>>> upper limits?
> > >>>>
> > >>>> ______________________________________________
> > >>>> R-help at r-project.org mailing list -- To
UNSUBSCRIBE and more, see
> > >>>> https://stat.ethz.ch/mailman/listinfo/r-help
> > >>>> PLEASE do read the posting guide
https://www.R-project.org/posting-
> > >>>> guide.html
> > >>>> and provide commented, minimal, self-contained,
reproducible code.
> > >>> Hello,
> > >>>
> > >>> Use ?mapply to cycle through all values of a and b.
> > >>> Note that the output matrices are transposed, the random
vectors are the
> > >>> rows.
> > >> Sorry, this is not true. The columns are the random vectors,
as
> > >> documented. An example setting the RNG seed, for
reproducibility.
> > >>
> > >>
> > >> library(Surrogate)
> > >>
> > >> a <- c(0.1, 0.2)
> > >> b <- c(0.2, 0.8)
> > >> set.seed(2025)
> > >> res <- mapply(\(a, b, s, n, m) RandVec(a, b, s, n, m),
> > >> MoreArgs = list(s = 1, n = 2, m = 5), a, b)
> > >>
> > >> res
> > >> #> $RandVecOutput
> > >> #> [,1] [,2] [,3] [,4] [,5]
> > >> #> [1,] 0.146079 0.1649319 0.1413759 0.257086 0.1715478
> > >> #> [2,] 0.253921 0.2350681 0.2586241 0.142914 0.2284522
> > >> #>
> > >> #> $RandVecOutput
> > >> #> [,1] [,2] [,3] [,4] [,5]
> > >> #> [1,] 0.5930918 0.2154583 0.6915523 0.7167089 0.3617918
> > >> #> [2,] 0.4069082 0.7845417 0.3084477 0.2832911 0.6382082
> > >>
> > >> lapply(res, colSums)
> > >> #> $RandVecOutput
> > >> #> [1] 0.4 0.4 0.4 0.4 0.4
> > >> #>
> > >> #> $RandVecOutput
> > >> #> [1] 1 1 1 1 1
> > >>
> > >>
> > >> Hope this helps,
> > >>
> > >> Rui Barradas
> > >>>
> > >>>
> > >>> library(Surrogate)
> > >>>
> > >>> a <- c(0.1, 0.2)
> > >>> b <- c(0.2, 0.8)
> > >>> mapply(\(a, b, s, n, m) RandVec(a, b, s, n, m),
> > >>> MoreArgs = list(s = 1, n = 2, m = 5), a, b)
> > >>> #> $RandVecOutput
> > >>> #> [,1] [,2] [,3] [,4]
[,5]
> > >>> #> [1,] 0.2004363 0.1552328 0.2391742 0.1744857
0.1949236
> > >>> #> [2,] 0.1995637 0.2447672 0.1608258 0.2255143
0.2050764
> > >>> #>
> > >>> #> $RandVecOutput
> > >>> #> [,1] [,2] [,3] [,4]
[,5]
> > >>> #> [1,] 0.2157416 0.4691191 0.5067447 0.7749258
0.7728955
> > >>> #> [2,] 0.7842584 0.5308809 0.4932553 0.2250742
0.2271045
> > >>>
> > >>>
> > >>> Hope this helps,
> > >>>
> > >>> Rui Barradas
> > >>>
> > >>>
> > >>
> > >>
> > >> --
> > >> Este e-mail foi analisado pelo software antiv?rus AVG para
verificar a presen?a de v?rus.
> > >> www.avg.com
> > Hello,
> >
> > The two blocks of res are the two random matrices, one for each
> > combination of (a,b). mapply passes each of the values in its
arguments
> > list (the ellipses in the help page) and computes the anonymous
function
> > with the pairs (a[1], b[1]), (a[2], b[2]).
> >
> > Since a and b are two elements vectors the output res is a two members
> > named list. Your error is to compare the result of apply(res2, 1, min)
> > to a, when you should compare to a[2]. See the code below.
> >
> >
> > library(Surrogate)
> > a <- c(0.015, 0.005)
> > b <- c(0.070, 0.045)
> > set.seed(2025)
> > res <- mapply(\(a, b, s, n, m) RandVec(a, b, s, n, m),
> > MoreArgs = list(s = 0.05528650577311, n = 2, m =
10000),
> > a, b)
> >
> > res1 = res[[1]]
> > res2 = res[[2]]
> >
> > # first check that the sums are correct
> > # these sums should be s = 0.05528650577311, up to floating-point
accuracy
> > lapply(res, \(x) colSums(x[, 1:5]) |> print(digits = 14L))
> > #> [1] 0.05528650577311 0.05528650577311 0.05528650577311
0.05528650577311
> > #> [5] 0.05528650577311
> > #> [1] 0.05528650577311 0.05528650577311 0.05528650577311
0.05528650577311
> > #> [5] 0.05528650577311
> > #> $RandVecOutput
> > #> [1] 0.05528651 0.05528651 0.05528651 0.05528651 0.05528651
> > #>
> > #> $RandVecOutput
> > #> [1] 0.05528651 0.05528651 0.05528651 0.05528651 0.05528651
> >
> > # now check the min and max
> > apply(res1, 1, min) > a[1L] ## [1] TRUE TRUE
> > #> [1] TRUE TRUE
> > apply(res2, 1, min) > a[2L] ## [1] TRUE TRUE
> > #> [1] TRUE TRUE
> >
> > apply(res1, 1, max) < b[1L] ## [1] TRUE TRUE
> > #> [1] TRUE TRUE
> > apply(res2, 1, max) < b[2L] ## [1] TRUE TRUE
> > #> [1] TRUE TRUE
> >
> >
> >
> > Which one should you take as final simulation of the vector? Both.
> > The first matrix values are bounded by c(a[1], b[1]) with column sums
> > equal to s.
> > The second matrix values are bounded by c(a[2], b[2]) with column sums
> > also equal to s.
> >
> > Hoep this helps,
> >
> > Rui Barradas
> >