Reputation: 503
I would like to use this code, which I found here: Generate N random integers that sum to M in R. I have a example data frame and I would like to use this function for each Value in data frame.
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
}
abc <- data.frame(Product = c("A", "B", "C"),
Value =c(33, 23, 12))
Upvotes: 0
Views: 65
Reputation: 102625
You can vectorize your function rand_vect
for receiving a array of values
vrand_vect <- Vectorize(rand_vect,"M",SIMPLIFY = F)
which gives
res <- vrand_vect(N= 7, M = abc$Value)
> res
[[1]]
[1] 3 5 6 6 4 3 6
[[2]]
[1] 1 3 4 5 3 4 3
[[3]]
[1] 1 2 3 3 1 2 0
Upvotes: 1
Reputation: 389235
You can use sapply
to run rand_vect
with N = 7
sapply(abc$Value, rand_vect, N = 7)
# [,1] [,2] [,3]
#[1,] 4 4 0
#[2,] 5 2 2
#[3,] 5 4 2
#[4,] 4 3 3
#[5,] 5 5 3
#[6,] 6 2 1
#[7,] 4 3 1
This will give 7 random numbers which will sum upto Value
.
We can verify it by
colSums(sapply(abc$Value, rand_vect, N = 7))
#[1] 33 23 12
Upvotes: 1