根据间隔内的分布生成随机数


17

我需要在区间内按照正态分布生成随机数。(我在R.工作)(a,b)

我知道函数rnorm(n,mean,sd)会按照正态分布生成随机数,但是如何在其中设置间隔限制?是否有任何特定的R函数可用?


为什么要这样做?如果它是有界的,那么它就不可能正常。您想达到什么目的?
gung-恢复莫妮卡

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

3
@Hugh太好了……只要您不在乎您会获得多少随机值。
Glen_b-恢复莫妮卡2014年

Answers:


31

听起来您想从截断的分布中模拟,在您的特定示例中,是从截断的normal中模拟。

这样做的方法有很多种,有些简单,有些相对有效。

我将在您的正常示例中说明一些方法。

  1. 这是一次非常简单的方法(一次生成某种伪代码)一次生成一个:

    repeat生成xi从N(均值,SD)until降低xi

    在此处输入图片说明

    如果大多数分布都在范围之内,这是很合理的,但是如果您几乎总是生成超出限制的范围,则它会变得很慢。

    在R中,您可以通过计算边界内的面积并生成足够的值来避免一次循环,从而可以几乎确定,在排除边界外的值之后,您仍然拥有所需的尽可能多的值。

  2. 您可以在该时间间隔内使用带有某些合适的主化功能的接受拒绝(在某些情况下,统一就足够了)。例如,如果限制相对于sd相对较窄,但距离您不远,则对统一法线进行适当的主化也可以。

    在此处输入图片说明

  3. 如果你有一个相当有效的cdf和逆CDF(如pnormqnorm用于R中的正态分布),可以使用在的模拟部分的第一段落中描述的逆CDF方法维基百科页面上的截断正常。[实际上,这与采用截断的制服(在要求的分位数处截短,实际上根本不需要拒绝,因为那只是另一种制服)相同,并对它应用逆法线cdf。请注意,如果您走得太远,这可能会失败]

    在此处输入图片说明

  4. 还有其他方法。相同的Wikipedia页面提到采用ziggurat方法,该方法适用于各种发行版。

相同的维基百科的链接中提到的两个具体包(无论在CRAN)与产生截断法线功能:

MSMR中的包具有函数,该函数rtnorm根据截断的法线来计算抽奖。truncnormR中的包还具有从截断法线绘制的功能。


环顾四周,其他问题的答案中涵盖了很多(但不是完全重复,因为这个问题比被截断的法线更笼统)...请参见

一种。这个答案

b。西安的回答在这里,与他的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)

我最近也遇到了同样的问题,试图为测试数据生成随机的学生成绩。在上面的代码中,我已使用pmaxpmin将边界值替换为最小或最大边界值。这对我来说是有效的,因为我生成的数据量很小,但是对于较大的数据量,最小值和最大值会给您带来明显的冲击。因此,根据您的目的,最好丢弃这些值,将它们替换为NAs,或者“重新滚动”它们直到入站。


为什么要这样做呢?生成普通随机数并丢弃那些需要截断的随机数是如此简单,以至于无需复杂,除非所需的截断接近密度区域的100%。
卡尔

2
也许我误解了最初的问题。我在尝试弄清楚如何在R中实现与统计信息不直接相关的编程任务时遇到了这个问题,现在我才注意到此页面是统计信息栈交换,而不是编程栈交换。:)就我而言,我想生成一定数量的随机整数,其值的范围从0到100,并且我希望生成的值落在该范围内的漂亮钟形曲线上。自编写此书以来,我已经意识到这sample(x=min:max, prob=dnorm(...))可能是一种更简单的方法。
亚伦·威尔斯

@Glen_b亚伦·威尔斯(Aaron Wells)提到sample(x=min:max, prob=dnorm(...)),这似乎比您的回答要短。
卡尔

但是请注意,该sample()技巧仅在您尝试选择随机整数或其他一些离散的预定义值集时才有用。
亚伦·威尔斯

1

a<b

ΦX1,...,XNμσ2a<b

Xi=μ+σΦ1(Ui)U1,...,UNIID U[Φ(aμσ),Φ(bμσ)].

没有用于截断分布生成值的内置函数,但是使用普通函数生成随机变量对该方法进行编程很简单。这是一个简单的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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.