Генерация случайных чисел после распределения в пределах интервала


17

Мне нужно генерировать случайные числа после нормального распределения в пределах интервала . (Я работаю в Р.)(a,b)

Я знаю, что функция rnorm(n,mean,sd)будет генерировать случайные числа после нормального распределения, но как установить пределы интервала в этом? Для этого есть какие-то особые функции R?


почему ты хочешь сделать это? Если он ограничен, тогда он не может быть нормальным. Чего ты пытаешься достичь?
gung - Восстановить Монику

x <- rnorm(n, mean, sd); x <- x[x > lower.limit & x < upper.limit]
Хью

3
@ Да, это здорово ... до тех пор, пока тебя не волнует, сколько случайных значений ты получишь.
Glen_b

Ответы:


31

Похоже, вы хотите смоделировать из усеченного дистрибутива , а в вашем конкретном примере, усеченного нормального .

Для этого существует множество методов, некоторые простые, некоторые относительно эффективные.

Я проиллюстрирую некоторые подходы на вашем обычном примере.

  1. Вот один очень простой метод для генерации по одному (в некотором псевдокоде):

    репеaT генерироватьИкся из N (среднее, стандартное отклонение)UNTяL понизитьИкся верхний

    введите описание изображения здесь

    Если большая часть распределения находится в пределах, это довольно разумно, но это может стать довольно медленным, если вы почти всегда генерируете за пределами.

    В R вы можете избежать цикла «один за раз», вычисляя область в пределах границ и генерируя достаточно значений, чтобы вы могли быть почти уверены, что после исключения значений за пределами у вас все еще будет столько значений, сколько необходимо.

  2. Вы можете использовать accept-reject с некоторой подходящей мажорирующей функцией на интервале (в некоторых случаях будет достаточно равномерного). Если бы пределы были достаточно узкими по отношению к SD, но вы не были далеко в хвосте, например, равномерное мажорирование будет работать нормально с нормой.

    введите описание изображения здесь

  3. Если у вас достаточно эффективный cdf и обратный cdf (такой как pnormи qnormдля нормального распределения в R), вы можете использовать метод обратного cdf, описанный в первом абзаце раздела о моделировании на странице Википедии на усеченной нормали . [По сути, это то же самое, что взять усеченную униформу (усеченную в требуемых квантилях, которая на самом деле вообще не требует отклонений, поскольку это просто еще одна униформа) и применить к ней обратный нормальный cdf. Обратите внимание, что это может потерпеть неудачу, если вы далеко в хвосте]

    введите описание изображения здесь

  4. Есть другие подходы; на той же странице Википедии упоминается адаптация метода зиккурата , который должен работать для различных дистрибутивов.

В той же ссылке в Википедии упоминаются два конкретных пакета (оба в CRAN) с функциями для генерации усеченных нормалей:

MSMПакет в R имеет функцию, rtnorm, которая вычисляет черпает из усеченных нормально. truncnormПакет в R также имеет функции для рисования из усеченных нормальных.


Оглядываясь вокруг, многое из этого покрыто ответами на другие вопросы (но не совсем дубликатами, так как этот вопрос является более общим, чем просто усеченная норма) ... см. Дополнительное обсуждение в

а. Этот ответ

б. Ответ Сианя здесь , где есть ссылка на его статью arXiv (наряду с некоторыми другими полезными ответами).


2

Быстрый и грязный подход заключается в использовании правила 68-95-99.7 .

При нормальном распределении 99,7% значений находятся в пределах 3 стандартных отклонений от среднего. Таким образом, если вы установите среднее значение на середину желаемого минимального значения и максимального значения и установите стандартное отклонение на 1/3 от среднего значения, вы получите (в основном) значения, попадающие в требуемый интервал. Тогда вы можете просто очистить все остальное.

minVal <- 0
maxVal <- 100
mn <- (maxVal - minVal)/2
# Generate numbers (mostly) from min to max
x <- rnorm(count, mean = mn, sd = mn/3)
# Do something about the out-of-bounds generated values
x <- pmax(minVal, x)
x <- pmin(maxVal, x)

Недавно я столкнулся с той же проблемой, пытаясь генерировать случайные оценки студентов для тестовых данных. В приведенном выше коде я использовал pmaxи pminдля замены значений за пределами поля на значение минимальной или максимальной границы. Это работает для моей цели, потому что я генерирую довольно небольшие объемы данных, но для больших объемов это даст вам заметные удары при минимальных и максимальных значениях. Поэтому, в зависимости от ваших целей, может быть лучше отбросить эти значения, заменить их на NAs или «перекатывать» их, пока они не окажутся в границах.


Зачем делать это? Сгенерировать нормальные случайные числа и отбросить те, которые требуют усечения, настолько просто, что нет необходимости в этом усложняться, если только желаемое усечение не близко к 100% площади плотности.
Карл

2
Возможно, я неправильно истолковываю исходный вопрос. Я столкнулся с этим вопросом, пытаясь выяснить, как выполнить задачу программирования, не связанную непосредственно со статистикой, в R, и только сейчас заметил, что эта страница является обменом стека статистики, а не обменом стека программирования. :) В моем случае я хотел сгенерировать определенное количество случайных целых чисел со значениями от 0 до 100, и я хотел, чтобы сгенерированные значения попадали на красивую кривую колокольчика в этом диапазоне. С тех пор, как я написал это, я понял, что sample(x=min:max, prob=dnorm(...))это может быть более простой способ сделать это.
Аарон Уэллс

@Glen_b Аарон Уэллс упоминает, sample(x=min:max, prob=dnorm(...))что кажется немного короче, чем ваш ответ.
Карл

Но учтите, что этот sample()трюк полезен только в том случае, если вы пытаетесь выбрать случайные целые числа или какой-то другой набор дискретных, предопределенных значений.
Аарон Уэллс

1

Ни один из ответов здесь не дает эффективного метода генерации усеченных нормальных переменных, который не предполагает отклонения произвольно большого числа сгенерированных значений. Если вы хотите сгенерировать значения из усеченного нормального распределения, с указанными нижними и верхними границамиa<б, это может быть сделано - без отклонения - путем генерации однородных квантилей в диапазоне квантилей, разрешенных усечением, и с использованием выборки обратного преобразования для получения соответствующих нормальных значений.

Позволять Φобозначим CDF стандартного нормального распределения. Мы хотим генерироватьИкс1,,,,,ИксN из усеченного нормального распределения (со средним параметром μ и параметр дисперсии σ2) с нижней и верхней границей усечения a<б, Это можно сделать следующим образом:

Иксязнак равноμ+σΦ-1(Uя)U1,,,,,UN~IID U[Φ(a-μσ),Φ(б-μσ)],

Не существует встроенной функции для сгенерированных значений из усеченного распределения, но программировать этот метод тривиально, используя обычные функции для генерации случайных величин. Вот простая Rфункция, rtruncnormкоторая реализует этот метод в несколько строк кода.

rtruncnorm <- function(N, mean = 0, sd = 1, a = -Inf, b = Inf) {
  if (a > b) stop('Error: Truncation range is empty');
  U <- runif(N, pnorm(a, mean, sd), pnorm(b, mean, sd));
  qnorm(U, mean, sd); }

Это векторизованная функция, которая будет генерировать Nслучайные величины IID из усеченного нормального распределения. Было бы легко программировать функции для других усеченных распределений тем же методом. Также не было бы слишком сложно программировать связанные функции плотности и квантили для усеченного распределения.


Обратите внимание, что усечение изменяет среднее значение и дисперсию распределения, поэтому μ и σ2это не среднее значение и дисперсия усеченного распределения.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.