Harmonyos应用实例195:用样本估计总体
·
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)
}
}
更多推荐



所有评论(0)