# 機能設計書 51-stats（統計関数）

## 概要

本ドキュメントは、Nim標準ライブラリの統計分析フレームワーク（stats.nim）について、その設計と仕様を詳細に記載した機能設計書である。

### 本機能の処理概要

statsモジュールは、データの基本的な統計分析を行うためのフレームワークを提供する。データは`RunningStat`または`RunningRegress`オブジェクトにプッシュされる際に単一パスで分析される。

**業務上の目的・背景**：科学計算、データ分析、機械学習、品質管理などの分野では、大量のデータに対して統計的な指標（平均、分散、標準偏差など）を効率的に計算する必要がある。本モジュールは、メモリ効率が良く、オンライン（ストリーミング）方式で統計値を計算できるアルゴリズムを提供し、データを1回のパスで処理することで計算効率を最大化する。

**機能の利用シーン**：
- リアルタイムデータストリームの統計監視
- 大規模データセットの効率的な統計計算
- 並列分析結果の結合（複数のRunningStatを加算して統合可能）
- 回帰分析における傾き、切片、相関係数の計算

**主要な処理内容**：
1. RunningStat型を使用した単一データセットの統計計算（n, min, max, sum, mean, variance, standardDeviation, skewness, kurtosis）
2. RunningRegress型を使用した2つのデータセット間の回帰分析（slope, intercept, correlation）
3. 複数のRunningStat/RunningRegressオブジェクトの結合（並列処理対応）
4. openArrayに対するヘルパー関数群

**関連システム・外部連携**：本モジュールは純粋なNim実装であり、外部ライブラリへの依存はない。std/mathモジュールからsqrt, pow, round関数をインポートして使用する。

**権限による制御**：特になし。すべての機能が任意のコードから利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本モジュールはライブラリ機能であり、直接の画面関連なし |

## 機能種別

計算処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|-----------------|
| x | float / int / openArray[float\|int] | Yes | 統計計算対象のデータ値 | 数値型であること |
| y | float / int / openArray[float\|int] | Yes (RunningRegress用) | 回帰分析の第2データセット | x配列と同じ長さであること |

### 入力データソース

- プログラムから直接渡される数値データ
- 配列・シーケンスからの一括プッシュ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| n | int | プッシュされたデータの数 |
| min | float | 最小値 |
| max | float | 最大値 |
| sum | float | 合計値 |
| mean | float | 平均値 |
| variance | float | 母分散 |
| varianceS | float | 標本分散 |
| standardDeviation | float | 母標準偏差 |
| standardDeviationS | float | 標本標準偏差 |
| skewness | float | 母歪度（第3統計モーメント） |
| skewnessS | float | 標本歪度 |
| kurtosis | float | 母尖度（第4統計モーメント） |
| kurtosisS | float | 標本尖度 |
| slope | float | 回帰直線の傾き |
| intercept | float | 回帰直線の切片 |
| correlation | float | 相関係数 |

### 出力先

呼び出し元への戻り値

## 処理フロー

### 処理シーケンス

```
1. RunningStat/RunningRegressオブジェクトの初期化
   └─ clear()プロシージャまたはデフォルト初期化で内部状態をリセット

2. データのプッシュ
   └─ push()プロシージャでデータを1つずつまたは配列で投入
   └─ 投入時にオンラインで統計モーメントを更新（Knuth TAOCP vol 2, 3rd edition, page 232のアルゴリズム）

3. 統計値の取得
   └─ mean(), variance(), standardDeviation()等のプロシージャを呼び出し
   └─ 内部の統計モーメントから計算して返却

4. （オプション）結果の結合
   └─ `+`演算子または`+=`演算子で複数のオブジェクトを結合
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[RunningStat初期化]
    B --> C{データあり?}
    C -->|Yes| D[push x]
    D --> E[統計モーメント更新]
    E --> F[n, min, max, sum更新]
    F --> G[mom1, mom2, mom3, mom4更新]
    G --> C
    C -->|No| H[統計値取得]
    H --> I[mean/variance/stddev等を計算]
    I --> J{並列結果あり?}
    J -->|Yes| K[+ 演算子で結合]
    K --> L[終了]
    J -->|No| L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | オンライン計算 | データは1回のパスで処理され、全データをメモリに保持しない | 常に適用 |
| BR-002 | 標本統計量 | varianceS, skewnessS, kurtosisS等は標本統計量として計算される | n > 1 または n > 2（skewnessS/kurtosisS用） |
| BR-003 | 並列結合可能性 | 複数のRunningStatは`+`演算子で数学的に正確に結合できる | 常に適用 |
| BR-004 | 回帰分析同長制約 | RunningRegressへのpushではx配列とy配列は同じ長さである必要がある | 配列をプッシュする場合 |

### 計算ロジック

**平均値（mom1）の更新**:
```nim
delta = x - mom1
delta_n = delta / n
mom1 = mom1 + delta_n
```

**分散（mom2）の更新**:
```nim
term1 = delta * delta_n * (n - 1)
mom2 = mom2 + term1
```

**歪度の計算**:
```nim
skewness = sqrt(n) * mom3 / pow(mom2, 1.5)
```

**尖度の計算**:
```nim
kurtosis = n * mom4 / (mom2 * mom2) - 3.0
```

**相関係数の計算**:
```nim
correlation = s_xy / (n * stddev_x * stddev_y)
```

## データベース操作仕様

### 操作別データベース影響一覧

本モジュールはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ゼロ除算 | n=0でvariance等を呼び出した場合 | n > 0を確認してから呼び出す |
| - | 無効値 | n < 2でvarianceSを呼び出した場合 | 0.0が返却される |
| - | アサーション失敗 | RunningRegress.pushでx,y配列の長さが異なる場合 | 配列の長さを揃える |

### リトライ仕様

リトライ不要（計算処理のため）

## トランザクション仕様

データベース操作がないため該当なし

## パフォーマンス要件

- すべての統計計算はO(1)の時間計算量で実行される（mean, variance等の取得時）
- データのプッシュはO(n)（n: プッシュするデータ数）
- メモリ使用量はO(1)（データ数に依存しない）

## セキュリティ考慮事項

- 計算処理のみであり、入力値の検証以外のセキュリティ考慮は不要
- 浮動小数点オーバーフローには注意が必要

## 備考

- アルゴリズムはKnuth TAOCP vol 2, 3rd edition, page 232に基づく
- `{.push debugger: off.}`, `{.push checks: off.}`によりパフォーマンス最適化が行われている

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、統計計算で使用されるデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | stats.nim | `lib/pure/stats.nim` | RunningStat型とRunningRegress型の定義（65-76行目） |

**読解のコツ**: `mom1`〜`mom4`は統計モーメントを表す。mom1が平均、mom2が分散計算用、mom3が歪度計算用、mom4が尖度計算用。

#### Step 2: エントリーポイントを理解する

処理の起点となるpushプロシージャを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | stats.nim | `lib/pure/stats.nim` | push(RunningStat, float)プロシージャ（90-110行目） |

**主要処理フロー**:
1. **90-98行目**: 最初のデータ時にmin/maxを初期化、それ以降は更新
2. **99-100行目**: nをインクリメントし、sumに加算
3. **101-110行目**: Knuthアルゴリズムによる統計モーメントの更新

#### Step 3: 統計値取得関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | stats.nim | `lib/pure/stats.nim` | mean, variance, varianceS等のプロシージャ（127-164行目） |

**主要処理フロー**:
- **127-129行目**: mean()はmom1をそのまま返却
- **131-133行目**: variance()はmom2/nで母分散を計算
- **135-138行目**: varianceS()はmom2/(n-1)で標本分散を計算

#### Step 4: 結合演算を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | stats.nim | `lib/pure/stats.nim` | `+`演算子（166-194行目） |

**読解のコツ**: 2つのRunningStatを数学的に正確に結合するための複雑な計算式。並列処理でデータを分割して処理した後、結果を統合する際に使用する。

#### Step 5: 回帰分析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | stats.nim | `lib/pure/stats.nim` | RunningRegressのpush, slope, intercept, correlation（274-336行目） |

### プログラム呼び出し階層図

```
ユーザーコード
    │
    ├─ RunningStat.push(x: float)
    │      └─ 統計モーメント更新（Knuthアルゴリズム）
    │
    ├─ RunningStat.push(x: int)
    │      └─ toFloat変換 → push(float)呼び出し
    │
    ├─ RunningStat.push(x: openArray)
    │      └─ 各要素に対してpush(float)をループ
    │
    ├─ mean(s: RunningStat) → float
    ├─ variance(s: RunningStat) → float
    ├─ standardDeviation(s: RunningStat) → float
    │      └─ sqrt(variance(s))
    │
    ├─ RunningRegress.push(x, y: float)
    │      ├─ s_xy累積計算
    │      └─ x_stats.push(x), y_stats.push(y)
    │
    └─ slope/intercept/correlation(r: RunningRegress)
           └─ 内部統計からの計算
```

### データフロー図

```
[入力]               [処理]                    [出力]

float/int値 ───▶ push() ───▶ mom1-4更新 ───▶ RunningStat内部状態

                     ↓
                mean() ───────────────────▶ 平均値(float)
                variance() ────────────────▶ 分散(float)
                standardDeviation() ───────▶ 標準偏差(float)
                skewness() ────────────────▶ 歪度(float)
                kurtosis() ────────────────▶ 尖度(float)

x,y float値 ───▶ RunningRegress.push() ───▶ 内部状態更新
                     ↓
                slope() ───────────────────▶ 傾き(float)
                intercept() ───────────────▶ 切片(float)
                correlation() ─────────────▶ 相関係数(float)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| stats.nim | `lib/pure/stats.nim` | ソース | 統計分析フレームワークの主要実装 |
| math.nim | `lib/pure/math.nim` | ソース | sqrt, pow等の数学関数を提供 |
