生成固定均值和标准差的随机数

28

使用rnorm(或runif等)在 R 中生成随机数时,它们很少与从中采样的分布具有相同的均值和标准差。是否有简单的一两行代码可以帮我实现这个功能?作为初步解决方案,我创建了这个函数,但它似乎应该是 R 或某个软件包本身就具有的功能。

# Draw sample from normal distribution with guaranteed fixed mean and sd
rnorm_fixed = function(n, mu=0, sigma=1) {
  x = rnorm(n)  # from standard normal distribution
  x = sigma * x / sd(x)  # scale to desired SD
  x = x - mean(x) + mu  # center around desired mean
  return(x)
}

举个例子:

x = rnorm(n=20, mean=5, sd=10)
mean(x)  # is e.g. 6.813...
sd(x)  # is e.g. 10.222...

x = rnorm_fixed(n=20, mean=5, sd=10)
mean(x)  # is 5
sd(x)  # is 10

我希望你能担任翻译,因为我在将分析应用于真实数据之前需要对模拟数据进行调整。这是有好处的,因为使用模拟数据时,我知道确切的属性(均值、标准差等),并且可以避免p值膨胀,因为我正在进行推论统计。我想问是否存在像“...”这样简单的东西。

rnorm(n=20, mean=5, sd=10, fixed=TRUE)

2
你可以使用函数 scale 来实现这个...但这不正是说明样本和总体统计之间的差异吗?随着你的 n 变大,sd(x)mean(x) 将接近你提供的值,但仅有 20 个样本,你不能期望完美的分布... - Justin
3
出于好奇,你为什么需要那个?我不会期望样本的均值和标准差与总体相同。 - Roland
2
我认为你已经做对了。我认为这很简单,人们只需要在需要时这样做。MASS::mvrnorm确实有类似的功能(但对于多元情况来说稍微棘手一些,这可能是为什么它被内置的原因)。同意@Justin的看法,你可以使用mu+sigma*scale(rnorm(n))作为一行代码。 - Ben Bolker
2
Justin和Roland:我已经在问题中添加了我的动机 :-) 这是因为我模拟数据并想要知道它的属性!所以,如果我想让这代表现实世界,这些限制就会很奇怪。但是我想要一个“完美的小世界”来玩耍,以便知道我是否做得正确 :-) - Jonas Lindeløv
我猜这应该是两行代码:x=rnorm(n) 和 x=(x-mean(x))/sd(x),这将重新标准化随机数据。 - Peter Dutton
显示剩余4条评论
3个回答

43

既然您要求只有一行:

rnorm2 <- function(n,mean,sd) { mean+sd*scale(rnorm(n)) }
r <- rnorm2(100,4,1)
mean(r)  ## 4
sd(r)    ## 1

从数学角度来看,这是否是不稳定的?一个人可以希望样本和其抽样自的总体均值相等,但不应该期望随机数样本和其总体的标准偏差相等。中心极限定理:(X1+...+Xn)/n -> N(mean,StdDev.)=N(mu, sigma/sqrt(n))。因此,对我而言,为了数学上的正确性,rnorm3必须定义为SD=sigma/sqrt(n) (sigma: 总体的标准偏差),m=mu。我想知道您对此问题的考虑。因此,如果您也认为需要根据CLT定义rnorm3,那么您如何正确地定义它呢? - Erdogan CEVHER
2
我想我找到了我的问题的答案。在上面的代码中,由于我们只从总体中抽取了一个样本(而不是从总体中抽取多个样本),因此人们可能希望得到样本和总体的均值和标准差的等价性。 - Erdogan CEVHER

4
MASS包中的mvrnorm()函数可以实现此功能。
library(MASS)
#empirical=T forces mean and sd to be exact
x <- mvrnorm(n=20, mu=5, Sigma=10^2, empirical=T)
mean(x)
sd(x)
#empirical=F does not impose this constraint
x <- mvrnorm(n=20, mu=5, Sigma=10^2, empirical=F
mean(x)
sd(x)

3
这是对先前答案中提出的函数的改进,以满足OP需要“固定”参数的要求。 并且仍保持一行格式;-)
rnorm. <- function(n=10, mean=0, sd=1, fixed=TRUE) { switch(fixed+1, rnorm(n, mean, sd), as.numeric(mean+sd*scale(rnorm(n)))) }
rnorm.() %>% {c(mean(.), sd(.))}
#### [1] 0 1
rnorm.(,,,F) %>% {c(mean(.), sd(.))}
#### [1] 0.1871827 0.8124567

我选择为每个参数输入默认值,并添加as.numeric步骤,以消除scale函数生成的属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接