我需要在区间内按照正态分布生成随机数。(我在R.工作)
我知道函数rnorm(n,mean,sd)
会按照正态分布生成随机数,但是如何在其中设置间隔限制?是否有任何特定的R函数可用?
x <- rnorm(n, mean, sd); x <- x[x > lower.limit & x < upper.limit]
我需要在区间内按照正态分布生成随机数。(我在R.工作)
我知道函数rnorm(n,mean,sd)
会按照正态分布生成随机数,但是如何在其中设置间隔限制?是否有任何特定的R函数可用?
x <- rnorm(n, mean, sd); x <- x[x > lower.limit & x < upper.limit]
Answers:
听起来您想从截断的分布中模拟,在您的特定示例中,是从截断的normal中模拟。
这样做的方法有很多种,有些简单,有些相对有效。
我将在您的正常示例中说明一些方法。
这是一次非常简单的方法(一次生成某种伪代码)一次生成一个:
生成从N(均值,SD)降低上
如果大多数分布都在范围之内,这是很合理的,但是如果您几乎总是生成超出限制的范围,则它会变得很慢。
在R中,您可以通过计算边界内的面积并生成足够的值来避免一次循环,从而可以几乎确定,在排除边界外的值之后,您仍然拥有所需的尽可能多的值。
您可以在该时间间隔内使用带有某些合适的主化功能的接受拒绝(在某些情况下,统一就足够了)。例如,如果限制相对于sd相对较窄,但距离您不远,则对统一法线进行适当的主化也可以。
如果你有一个相当有效的cdf和逆CDF(如pnorm
和qnorm
用于R中的正态分布),可以使用在的模拟部分的第一段落中描述的逆CDF方法维基百科页面上的截断正常。[实际上,这与采用截断的制服(在要求的分位数处截短,实际上根本不需要拒绝,因为那只是另一种制服)相同,并对它应用逆法线cdf。请注意,如果您走得太远,这可能会失败]
还有其他方法。相同的Wikipedia页面提到采用ziggurat方法,该方法适用于各种发行版。
在相同的维基百科的链接中提到的两个具体包(无论在CRAN)与产生截断法线功能:
MSM
R中的包具有函数,该函数rtnorm
根据截断的法线来计算抽奖。truncnorm
R中的包还具有从截断法线绘制的功能。
环顾四周,其他问题的答案中涵盖了很多(但不是完全重复,因为这个问题比被截断的法线更笼统)...请参见
一种。这个答案
b。西安的回答在这里,与他的arXiv论文有链接(以及其他一些有价值的回复)。
快捷方法是使用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
将边界值替换为最小或最大边界值。这对我来说是有效的,因为我生成的数据量很小,但是对于较大的数据量,最小值和最大值会给您带来明显的冲击。因此,根据您的目的,最好丢弃这些值,将它们替换为NA
s,或者“重新滚动”它们直到入站。
sample(x=min:max, prob=dnorm(...))
可能是一种更简单的方法。
sample(x=min:max, prob=dnorm(...))
,这似乎比您的回答要短。
sample()
技巧仅在您尝试选择随机整数或其他一些离散的预定义值集时才有用。
没有用于截断分布生成值的内置函数,但是使用普通函数生成随机变量对该方法进行编程很简单。这是一个简单的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随机变量。通过相同的方法为其他截断的分布编写函数很容易。为截断的分布编程相关的密度和分位数函数也不会太困难。