6. 数据统计分析工具

功能简介:输入一组数据,自动计算均值、中位数、众数、方差等统计量,生成直方图。这是一个功能丰富的几何与数据工具集合,包含几何体表面积与体积计算、3D模型与展开图展示、空间点线面关系交互演示、直线方程求解与可视化、圆方程计算与直线位置关系分析,以及数据统计分析与直方图生成等功能。界面设计直观,操作流畅,支持实时参数调整和可视化反馈,是学习几何概念和数据分析的理想工具。
在这里插入图片描述
ArkTS代码

@Entry
@Component
struct DataAnalyzer {
  @State private data: string = '1,2,3,4,5,6,7,8,9,10'
  @State private statistics: string = ''
  @State private histogramData: number[] = []
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Column() {
      Text('📊 数据统计分析')
        .fontSize(24).fontWeight(FontWeight.Bold)

      TextInput({ placeholder: '输入数据,用逗号分隔', text: this.data })
        .width('90%')
        .onChange((v: string) => this.data = v)

      Button('分析数据')
        .onClick(() => this.analyzeData())

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

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

  private analyzeData() {
    // 解析数据
    const numbers: number[] = this.data.split(',')
      .map(s => parseFloat(s.trim()))
      .filter(n => !isNaN(n))
    
    if (numbers.length === 0) {
      this.statistics = '请输入有效的数字数据'
      return
    }
    
    // 计算统计量
    const mean = this.calculateMean(numbers)
    const median = this.calculateMedian(numbers)
    const mode = this.calculateMode(numbers)
    const variance = this.calculateVariance(numbers, mean)
    const stdDev = Math.sqrt(variance)
    const min = Math.min(...numbers)
    const max = Math.max(...numbers)
    const range = max - min
    
    // 生成直方图数据
    this.histogramData = this.generateHistogramData(numbers, min, max)
    
    // 显示统计结果
    const modeStr = mode[0] === -1 ? '无' : mode.join(', ')
    this.statistics = `均值: ${mean.toFixed(2)} | 中位数: ${median.toFixed(2)} | 众数: ${modeStr}
方差: ${variance.toFixed(2)} | 标准差: ${stdDev.toFixed(2)} | 极差: ${range.toFixed(2)}
最小值: ${min.toFixed(2)} | 最大值: ${max.toFixed(2)} | 样本数: ${numbers.length}`
    
    // 重绘直方图
    this.drawHistogram(this.context)
  }
  
  private calculateMean(numbers: number[]): number {
    const sum = numbers.reduce((acc, val) => acc + val, 0)
    return sum / numbers.length
  }
  
  private calculateMedian(numbers: number[]): number {
    const sorted = [...numbers].sort((a, b) => a - b)
    const mid = Math.floor(sorted.length / 2)
    if (sorted.length % 2 === 0) {
      return (sorted[mid - 1] + sorted[mid]) / 2
    } else {
      return sorted[mid]
    }
  }
  
  private calculateMode(numbers: number[]): number[] {
    const frequency: Map<number, number> = new Map()
    numbers.forEach(num => {
      frequency.set(num, (frequency.get(num) || 0) + 1)
    })
    
    const values: number[] = Array.from(frequency.values())
    let maxFreq: number = 0
    for (let i = 0; i < values.length; i++) {
      if (values[i] > maxFreq) {
        maxFreq = values[i]
      }
    }
    if (maxFreq === 1) return [-1]
    
    const result: number[] = []
    frequency.forEach((freq, num) => {
      if (freq === maxFreq) {
        result.push(num)
      }
    })
    return result
  }
  
  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 generateHistogramData(numbers: number[], min: number, max: number): number[] {
    const binCount = 10
    const binWidth = (max - min) / binCount
    const bins: number[] = new Array(binCount).fill(0)
    
    numbers.forEach(num => {
      const binIndex = Math.min(Math.floor((num - min) / binWidth), binCount - 1)
      bins[binIndex]++
    })
    
    return bins
  }

  private drawHistogram(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.histogramData.length === 0) return
    
    // 绘制直方图
    const maxCount = Math.max(...this.histogramData)
    const barWidth = width / this.histogramData.length
    
    this.histogramData.forEach((count, index) => {
      const barHeight = (count / maxCount) * (height - 40)
      const x = index * barWidth
      const y = height - barHeight - 20
      
      // 绘制柱子
      ctx.fillStyle = '#2196F3'
      ctx.fillRect(x + 2, y, barWidth - 4, barHeight)
      
      // 绘制数值
      if (count > 0) {
        ctx.fillStyle = '#333333'
        ctx.font = '10px sans-serif'
        ctx.fillText(count.toString(), x + barWidth / 2 - 3, y - 5)
      }
    })
    
    // 绘制坐标轴
    ctx.strokeStyle = '#666666'
    ctx.lineWidth = 1
    ctx.beginPath()
    ctx.moveTo(0, height - 20)
    ctx.lineTo(width, height - 20)
    ctx.stroke()
  }
}
Logo

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

更多推荐