1

I am using this code that generates 3 random numbers that add to 72:

# https://stackoverflow.com/questions/24845909/generate-n-random-integers-that-sum-to-m-in-r
rand_vect <- function(N, M, sd = 1, pos.only = TRUE) {
    vec <- rnorm(N, M/N, sd)
    if (abs(sum(vec)) < 0.01) vec <- vec + 1
    vec <- round(vec / sum(vec) * M)
    deviation <- M - sum(vec)
    for (. in seq_len(abs(deviation))) {
        vec[i] <- vec[i <- sample(N, 1)] + sign(deviation)
    }
    if (pos.only) while (any(vec < 0)) {
        negs <- vec < 0
        pos  <- vec > 0
        vec[negs][i] <- vec[negs][i <- sample(sum(negs), 1)] + 1
        vec[pos][i]  <- vec[pos ][i <- sample(sum(pos ), 1)] - 1
    }
    vec
}

If I run this code 100 times:

results <- list()

for (i in 1:100)

{

r_i = rand_vect(3,72)

results[[i]] <- r_i


}

When I look at the numbers that came out:

[[1]]
[1] 23 24 25

[[2]]
[1] 25 24 23

[[3]]
[1] 24 25 23

[[4]]
[1] 23 24 25

[[5]]
[1] 25 24 23

[[6]]
[1] 24 24 24

[[7]]
[1] 24 25 23

[[8]]
[1] 24 25 23

[[9]]
[1] 24 25 23

[[10]]
[1] 24 23 25

In each iteration, all the numbers add to 72 as expected - but the numbers don't really "look that random". They all seem to be "clumped" around "24, 23, 25". I was hoping to see more "randomness" in these numbers. For example:

[[11]] [1] 5 50 17

[[12]] [1] 12 40 20

  • Why are the numbers in the code I am using "clumped" around 24, 23, 25 - and how can I change the above code so that there is more "randomness" in the numbers being generated?

Thank you!

stats_noob
  • 5,401
  • 4
  • 27
  • 83
  • 4
    No comment on the overall strategy, but your `sd = 1` is why everything is so close. Increase that and you'll see more variation. –  Apr 22 '22 at 14:53
  • Adam : I think this was the problem! Thank you! – stats_noob Apr 22 '22 at 14:55
  • You don't really need to change `sd = 1` part. You can just pass a third parameter when you call `rand_vect`, such as: `rand_vect(3, 72, 20)`. – Jerry Coffin Apr 22 '22 at 14:59

1 Answers1

8

If you just want three random integers that sum to 72 you could do something like

diff(c(0, sort(sample(72, 2)), 72))
Andrew Gustar
  • 17,295
  • 1
  • 22
  • 32
  • 1
    Andrew: This is a very cool answer! And it even works for more than 3 numbers! Can you please explain how this works - and how this code is able to add more 'randomness' to the numbers being generated? thanks! – stats_noob Apr 22 '22 at 14:57
  • 3
    @antonoyaro8 It picks two numbers - say x and y (x <= y ) - between 0 and 72 and treats the sequence (0, x, y, 72) as a cumulative sequence. `diff` then takes the difference of these elements, leaving x, y-x, and 72-y as your three numbers. – Andrew Gustar Apr 22 '22 at 15:01