7. 用样本估计总体

功能简介:模拟抽样过程,展示样本统计量如何估计总体参数,理解抽样分布。抽样模拟功能通过生成正态分布总体数据,进行多次随机抽样,计算样本均值并分析其分布特性,直观展示样本统计量如何估计总体参数。支持调整总体大小、样本大小和模拟次数,实时绘制样本均值分布直方图,显示总体参数与样本均值分布参数对比,帮助理解抽样分布和中心极限定理,是统计学教学和学习的理想工具。
在这里插入图片描述
ArkTS代码

@Entry
@Component
struct SampleEstimation {
  @State private populationSize: number = 1000
  @State private sampleSize: number = 50
  @State private trials: number = 100
  @State private result: string = ''
  @State private sampleMeans: number[] = []
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Column() {
      Text('🎯 用样本估计总体')
        .fontSize(24).fontWeight(FontWeight.Bold)

      Row() {
        Text('总体大小: ')
        Slider({ value: this.populationSize, min: 100, max: 10000 })
          .onChange((val: number) => this.populationSize = val)
      }

      Row() {
        Text('样本大小: ')
        Slider({ value: this.sampleSize, min: 10, max: 200 })
          .onChange((val: number) => this.sampleSize = val)
      }

      Row() {
        Text('模拟次数: ')
        Slider({ value: this.trials, min: 10, max: 1000 })
          .onChange((val: number) => this.trials = val)
      }

      Button('开始模拟')
        .onClick(() => this.simulateSampling())

      Canvas(this.context)
        .width(300).height(200)
        .onReady(() => this.drawDistribution(this.context))

      Text(this.result)
        .fontSize(14).fontColor('#666')
    }
  }

  private simulateSampling() {
    // 生成总体数据(正态分布)
    const population: number[] = []
    const populationMean = 50
    const populationStdDev = 10
    
    for (let i = 0; i < this.populationSize; i++) {
      // 生成正态分布随机数
      const u1 = Math.random()
      const u2 = Math.random()
      const z0 = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2)
      const value = populationMean + z0 * populationStdDev
      population.push(value)
    }
    
    // 计算总体参数
    const trueMean = this.calculateMean(population)
    const trueStdDev = Math.sqrt(this.calculateVariance(population, trueMean))
    
    // 进行多次抽样
    this.sampleMeans = []
    for (let i = 0; i < this.trials; i++) {
      // 随机抽样
      const sample: number[] = []
      for (let j = 0; j < this.sampleSize; j++) {
        const index = Math.floor(Math.random() * this.populationSize)
        sample.push(population[index])
      }
      
      // 计算样本均值
      const sampleMean = this.calculateMean(sample)
      this.sampleMeans.push(sampleMean)
    }
    
    // 计算样本均值的分布参数
    const meanOfMeans = this.calculateMean(this.sampleMeans)
    const stdDevOfMeans = Math.sqrt(this.calculateVariance(this.sampleMeans, meanOfMeans))
    
    // 显示结果
    this.result = `总体参数:均值 = ${trueMean.toFixed(2)}, 标准差 = ${trueStdDev.toFixed(2)}
样本均值分布:均值 = ${meanOfMeans.toFixed(2)}, 标准差 = ${stdDevOfMeans.toFixed(2)}
标准误(理论值):${(trueStdDev / Math.sqrt(this.sampleSize)).toFixed(2)}
模拟次数:${this.trials}, 样本大小:${this.sampleSize}`
    
    // 绘制抽样分布
    this.drawDistribution(this.context)
  }
  
  private calculateMean(numbers: number[]): number {
    const sum = numbers.reduce((acc, val) => acc + val, 0)
    return sum / numbers.length
  }
  
  private calculateVariance(numbers: number[], mean: number): number {
    const sumSquaredDiff = numbers.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0)
    return sumSquaredDiff / numbers.length
  }

  private drawDistribution(ctx: CanvasRenderingContext2D) {
    const width = 300
    const height = 200
    
    // 清空画布
    ctx.clearRect(0, 0, width, height)
    ctx.fillStyle = '#F5F5F5'
    ctx.fillRect(0, 0, width, height)
    
    if (this.sampleMeans.length === 0) return
    
    // 计算直方图数据
    const min = Math.min(...this.sampleMeans)
    const max = Math.max(...this.sampleMeans)
    const binCount = 20
    const binWidth = (max - min) / binCount
    const bins: number[] = new Array(binCount).fill(0)
    
    for (let i = 0; i < this.sampleMeans.length; i++) {
      const binIndex = Math.min(Math.floor((this.sampleMeans[i] - min) / binWidth), binCount - 1)
      bins[binIndex]++
    }
    
    // 绘制直方图
    const maxCount = Math.max(...bins)
    const barWidth = width / binCount
    
    for (let i = 0; i < bins.length; i++) {
      const count = bins[i]
      const barHeight = (count / maxCount) * (height - 40)
      const x = i * barWidth
      const y = height - barHeight - 20
      
      // 绘制柱子
      ctx.fillStyle = '#2196F3'
      ctx.fillRect(x + 2, y, barWidth - 4, barHeight)
    }
    
    // 绘制坐标轴
    ctx.strokeStyle = '#666666'
    ctx.lineWidth = 1
    ctx.beginPath()
    ctx.moveTo(0, height - 20)
    ctx.lineTo(width, height - 20)
    ctx.stroke()
    
    // 绘制标题
    ctx.fillStyle = '#333333'
    ctx.font = '12px sans-serif'
    ctx.fillText('样本均值分布', 10, 20)
  }
}
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐