在R中生成近似标准正态分布样本的高效方法探究
这问题我太有共鸣了——想要生成外观尽可能贴合标准正态分布的固定样本量(比如n=100)数据,又不想用那种重复上万次模拟再取均值的低效方法对吧?
问题回顾
你一开始尝试直接用rnorm(100),但样本变异性太大,密度曲线波动明显;后来找到的rowMeans(replicate(10000, sort(rnorm(100, 0, 1))))方法效果不错,但重复模拟上万次确实很耗时,尤其是样本量更大的时候。而常规的qnorm方法(比如用seq(.00001, .99999, length.out = 100))又因为分位数边界选得太极端,导致样本尾部偏离理论分布,效果不如均值方法。
高效确定性解决方案
核心思路是调整qnorm的分位数边界,让分位数间隔与样本量n挂钩,具体代码如下:
n <- 100 # 优化后的qnorm方法 x <- qnorm(seq(1/n, 1-1/n, length.out = n), mean = 0, sd = 1) plot(density(x), main = "优化分位数边界的近似正态样本")
为什么这个方法有效?
常规qnorm用极端小/大的分位数(比如0.00001)会把样本点强行拉到正态分布的极尾部,导致密度曲线出现不必要的“翘曲”;而用1/n和1-1/n作为分位数的起止点,相当于给n个样本点分配了均匀间隔的理论分位数位置,刚好对应n个样本在理想正态分布中的期望位置,完美避免了极端值的干扰。
这个方法的效果和你之前的均值方法几乎完全一致,但它是纯确定性的计算,不需要任何重复模拟,效率提升了几个数量级——哪怕n增大到1000,计算也能瞬间完成。
可选微调:更平滑的尾部
如果对尾部的平滑度有更高要求,可以把分位数边界调整为1/(2n)到1-1/(2n),这是统计学中常用的“分位数填充”技巧,能让样本点更贴合理论分布的中位数位置:
x <- qnorm(seq(1/(2*n), 1-1/(2*n), length.out = n), mean = 0, sd = 1)
对于n=100来说,两种边界的差异非常小,你可以根据自己的需求选择。
方法对比代码
你可以运行下面的代码直观对比四种方法的效果:
n <- 100 # 常规rnorm样本 x_rnorm <- rnorm(n) # 常规qnorm样本 x_qnorm <- qnorm(seq(.00001, .99999, length.out = n)) # 优化qnorm样本 x_opt <- qnorm(seq(1/n, 1-1/n, length.out = n)) # 原均值方法样本 x_mean <- rowMeans(replicate(10000, sort(rnorm(n)))) # 多图对比 par(mfrow = c(2, 2)) plot(density(x_rnorm), main = "常规rnorm样本", col = "red", lwd = 2) plot(density(x_qnorm), main = "常规qnorm样本", col = "blue", lwd = 2) plot(density(x_opt), main = "优化qnorm样本", col = "green", lwd = 2) plot(density(x_mean), main = "原均值方法样本", col = "purple", lwd = 2)
运行后你会发现,绿色的优化qnorm曲线和紫色的原均值方法曲线几乎完全重合,而效率却天差地别。
内容的提问来源于stack exchange,提问作者Dominique Makowski

