Sample with a max

前端 未结 5 1228
日久生厌
日久生厌 2021-01-19 01:57

If I want to sample numbers to create a vector I do:

set.seed(123)
x <- sample(1:100,200, replace = TRUE)
sum(x)
# [1] 10228

What if I

5条回答
  •  一整个雨季
    2021-01-19 02:31

    Another approach, but with floating point numbers, so not exactly what you are looking for, sorry :

    randomsum <- function(nb, sum) {
      tmp <- sort(runif(nb-1))
      tmp <- c(min(tmp), diff(tmp), 1-max(tmp))
      as.vector(quantile(0:sum, probs=tmp))
    }
    

    Which would give for example :

    R> result <- randomsum(10, 1000)
    R> result
     [1]  35.282191  66.537308  17.263761 182.837409 120.064363 210.752735
     [7] 143.201079   6.164731  34.936359 182.960064
    R> sum(result)
    [1] 1000
    

    You could use round on the result to get integers, but then of course the sum could be slightly different from what you want to get. A quick and dirty workaround can be to alter one of the random values to make your vector sum to the number you want :

    randomsumint <- function(nb, sum) {
      tmp <- sort(runif(nb-1))
      tmp <- c(min(tmp), diff(tmp), 1-max(tmp))
      res <- as.vector(quantile(0:sum, probs=tmp))
      res <- round(res)
      res[length(res)] <- res[length(res)]+(sum-sum(res))
      res
    }
    

    Which would give :

    R> result <- randomsumint(10,1000)
    R> result
     [1]  42 152   0  11  74 138   9 138 172 264
    R> sum(result)
    [1] 1000
    

    Not that this is far from perfect, as in some rare cases you could get a negative value in your result.

提交回复
热议问题