Генерация неотрицательных (или положительных) случайных целых чисел, которые суммируются с фиксированным значением - PullRequest
0 голосов
/ 28 сентября 2018

Я бы хотел случайным образом назначить положительные целые числа группам G, чтобы они суммировались до V.

Например, если G = 3 и V = 21Допустимые результаты: (7, 7, 7), (10, 6, 5) и т. д.

Есть ли простой способ сделать это?


Уведомление редактора (из 李哲源):

Если значения не ограничены целыми числами, проблема проста и решена в Выбор n чисел с фиксированной суммой .

Для целых чисел существует предыдущий Q & A: Генерирует N случайных целых чисел, которые суммируются с M в R , но это кажется более сложным и трудным для понимания.Решение, основанное на цикле, также не удовлетворяет.

Ответы [ 2 ]

0 голосов
/ 28 сентября 2018

неотрицательные целые числа

Пусть n будет размером выборки:

x <- rmultinom(n, V, rep.int(1 / G, G))

- это матрица G x n, где каждый столбец представляет собой полиномиальный образецэто суммирует до V.

Передав rep.int(1 / G, G) аргументу prob Я предполагаю, что каждая группа имеет равную вероятность "успеха".


натуральные числа

Как упоминает Грегор , полиномиальная выборка может содержать 0. Если такие выборки нежелательны, они должны быть отклонены.В результате мы производим выборку из усеченного полиномиального распределения.

In Как создать целевое число выборок из распределения по критерию отклонения Я предложил подход «избыточной выборки» для достижения«векторизация» для усеченной выборки.Проще говоря, зная вероятность принятия, мы можем оценить ожидаемое количество испытаний M, чтобы увидеть первый «успех» (не ноль).Сначала мы скажем 1.25 * M выборок, затем будет хотя бы один «успех» в этих выборках.Мы случайным образом возвращаем единицу в качестве вывода.

Следующая функция реализует эту идею для генерации усеченных многочленных семплов без 0.

positive_rmultinom <- function (n, V, prob) {
  ## input validation
  G <- length(prob)
  if (G > V) stop("'G > V' causes 0 in a sample for sure!")
  if (any(prob < 0)) stop("'prob' can not contain negative values!")
  ## normalization
  sum_prob <- sum(prob)
  if (sum_prob != 1) prob <- prob / sum_prob
  ## minimal probability
  min_prob <- min(prob)
  ## expected number of trials to get a "success" on the group with min_prob
  M <- round(1.25 * 1 / min_prob)
  ## sampling
  N <- n * M
  x <- rmultinom(N, V, prob)
  keep <- which(colSums(x == 0) == 0)
  x[, sample(keep, n)]
  }

Теперь давайте попробуем

V <- 76
prob <- c(53, 13, 9, 1)

Непосредственноиспользование rmultinom для рисования образцов может иногда приводить к получению с 0:

## number of samples that contain 0 in 1000 trials
sum(colSums(rmultinom(1000, V, prob) == 0) > 0)
#[1] 355   ## or some other value greater than 0

Но такой проблемы нет при использовании positive_rmultinom:

## number of samples that contain 0 in 1000 trials
sum(colSums(positive_rmultinom(1000, V, prob) == 0) > 0)
#[1] 0
0 голосов
/ 28 сентября 2018

Вероятно, менее дорогой способ, но, похоже, это работает.

G <- 3
V <- 21
m <- data.frame(matrix(rep(1:V,G),V,G))
tmp <- expand.grid(m) # all possibilities
out <- tmp[which(rowSums(tmp) == V),] # pluck those that sum to 'V'
out[sample(1:nrow(out),1),] # randomly select a column

Не уверен, как поступить с runif

...