这段代码是否演示了中心极限定理?

机器算法验证 r 中心极限定理
2022-03-10 11:55:49

这段代码是否演示了中心极限定理?这不是家庭作业!相反,我是一名教非统计学学生一些方法的教师。

library(tidyverse)
#Make fake data
population<-rnorm(1000000, mean=100, sd=10)

#Draw 100 samples of size 5
map(1:100, ~sample(population, size=5)) %>% 
  #calculate their mean
  map(., mean) %>% 
  #unlist 
  unlist() %>% 
  #draw histogram of sample means
  hist(, xlim=c(80,120))

#Repeat but with sample size 500
map(1:100, ~sample(population, size=500)) %>% 
  map(., mean) %>% 
  unlist() %>% 
  hist(., xlim=c(80,120))

#Repeat but with sample size 1000
map(1:100, ~sample(population, size=1000)) %>% 
  map(., mean) %>% 
  unlist() %>% 
  hist(., xlim=c(80,120))



3个回答

这是几行完整的研究。

对于给定的一组样本大小n和基础分布r,它会n.sim从该分布生成每个大小的独立样本,标准化它们的均值的经验分布,绘制直方图,并以红色叠加标准正态密度。 CLT 表示,当基础分布具有有限方差时,红色曲线越来越接近直方图。

数据

前三行说明了样本大小的过程10,20,100,500以及基础正态分布、伽玛分布和伯努利分布。随着样本量的增加,近似值明显变好。底行使用柯西分布。因为 CLT(有限方差)的一个关键假设在这种情况下不成立,所以它的结论不成立,这很清楚。

执行时间约为一秒。

f <- function(n, r=rnorm,  n.sim=1e3, name="Normal", ...) {
  sapply(n, function(n) {
    x <- scale(colMeans(matrix(r(n*n.sim, ...), n))) # Sample, take mean, standardize
    hist(x, sub=name, main=n, freq=FALSE, breaks=30) # Plot distribution
    curve(dnorm(x), col="Red", lwd=2, add=TRUE)      # Compare to standard Normal
  })
}
n <- c(5,20,100,500)
mfrow.old <- par(mfrow=c(4,length(n)))
f(n)
f(n, rgamma, shape=1/2, name="Gamma(1/2)")
f(n, function(n) runif(n) < 0.9, name="Bernoulli(9/10)")
f(n, rt, df=1, name="Cauchy")
par(mfrow=mfrow.old)

这是我从评论中提出的建议之一。大小为 n=100000 的样本均值(大约需要 20 秒左右,请耐心等待):

  ln.mean = replicate(1000,mean(rlnorm(100000,0,4)))
  hist(ln.mean,n=100)

样本量为 100000 的均值直方图

即使在如此巨大的样本量下,样本均值的分布仍然非常偏斜——但中心极限定理仍然适用于此——即使是“经典”CLT。

也许使用类似以下(更简单,更直接)的 R 代码来显示十几个标准均匀随机变量的平均值很难与正常区分开来。

set.seed(1126)
a = replicate(5000, mean(runif(12))
shapiro.test(a)

        Shapiro-Wilk normality test

data:  a
W = 0.99965, p-value = 0.565

plot(qqnorm(a))

在此处输入图像描述

然后使用 R 代码显示 50 甚至 100 个标准指数随机变量的平均值很容易与正常区分开来。什么是分布A=X¯100?

set.seed(1127)
a = replicate(5000, mean(rexp(100)))
shapiro.test(a)$p.val
 [1] 1.675877e-06

然而,1000 个标准指数的平均值更难与正常区分开来。

set.seed(1127)
a = replicate(5000, mean(rexp(1000)))
shapiro.test(a)$p.val
[1] 0.2413559