# 機能設計書 16-summarise

## 概要

本ドキュメントは、dplyrパッケージの`summarise()`関数（`summarize()`のシノニム）に関する機能設計書である。この関数は、データフレームの各グループを単一の行に集約するための機能を提供する。

### 本機能の処理概要

`summarise()`関数は、データフレームを集約して新しいデータフレームを作成する。グループ化されたデータフレームの場合は各グループごとに1行を返し、グループ化されていない場合は全体で1行を返す。各集約式は長さ1の値を返す必要がある。

**業務上の目的・背景**：データ分析において、大量のデータを意味のある要約統計量（平均、合計、件数、標準偏差など）に集約することは最も基本的かつ重要な操作である。売上データの月次集計、顧客セグメント別の行動指標計算、製品カテゴリ別の在庫状況把握など、ビジネスのあらゆる場面で集約処理が必要となる。`summarise()`は、このような集約操作を直感的かつ効率的に実現するための中核機能を提供する。

**機能の利用シーン**：
- グループごとの集計（平均、合計、件数、最大、最小など）
- 統計量の計算（標準偏差、分散、四分位数など）
- 複数の集計指標を一度に計算
- グループ化されたデータの要約レポート作成
- データの前処理としての集約

**主要な処理内容**：
1. `UseMethod()`によるメソッドディスパッチ
2. `.by`引数または既存グループによるグループ情報の取得
3. `summarise_cols()`で各集約式を評価
4. 各グループで各式が長さ1を返すことを検証
5. `summarise_build()`で出力データフレームを構築
6. `.groups`引数に基づいて出力のグループ構造を決定

**関連システム・外部連携**：`group_by()`でグループ化されたデータフレームと連携。`across()`で複数列に同じ集計を適用可能。`n()`、`mean()`、`sum()`などの集計関数と組み合わせて使用。

**権限による制御**：本機能はRパッケージの一部であり、特定の権限制御は存在しない。関数を呼び出す全てのユーザーが同じ機能を利用可能である。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | 本機能はRライブラリ（dplyr）のため画面は存在しない |

## 機能種別

データ集計処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| .data | data.frame | Yes | 操作対象のデータフレーム | data.frameまたはその派生クラスであること |
| ... | data-masking | No | 名前付きの集計式 | 各式が長さ1の値を返すこと |
| .by | tidy-select | No | 一時的なグループ化変数 | grouped_df/rowwise_dfでは使用不可 |
| .groups | character | No | 出力のグループ構造を制御 | "drop_last", "drop", "keep", "rowwise"のいずれか |

### 入力データソース

- Rセッション内のdata.frame、tibble、grouped_df、rowwise_df、またはその派生クラスのオブジェクト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | data.frame/grouped_df/rowwise_df | 集約されたデータフレーム |

### 出力先

- Rセッション内のオブジェクトとして返却

### 出力特性

- 行はグループキーから生成される
- 列はグループ変数と集計式の結果の組み合わせ
- グループ構造は`.groups`引数で制御
- データフレーム属性は保持されない（新しいデータフレームが作成される）

## 処理フロー

### 処理シーケンス

```
1. UseMethod("summarise")によるメソッドディスパッチ
   └─ .dataの型に応じた適切なメソッドが呼び出される
2. .byと.groupsの排他チェック
   └─ 両方指定はエラー
3. compute_by()でグループ情報を取得
4. summarise_cols()で集計式を評価
   ├─ DataMaskを作成
   ├─ 各式を評価し、長さ1を検証
   └─ 結果をchunksとして収集
5. summarise_build()で出力を構築
   └─ グループキーと集計結果を結合
6. .groupsに基づいて出力構造を決定
   ├─ "drop_last": 最後のグループを削除
   ├─ "drop": 全グループを削除
   ├─ "keep": グループ構造を維持
   └─ "rowwise": 行ごとのグループに変換
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[summarise呼び出し]
    B --> C[UseMethodでディスパッチ]
    C --> D{.byと.groups両方指定?}
    D -->|Yes| E[エラー]
    D -->|No| F[compute_byでグループ取得]
    F --> G[summarise_colsで式評価]
    G --> H{各式が長さ1?}
    H -->|No| I[エラー: reframe使用を提案]
    H -->|Yes| J[summarise_buildで出力構築]
    J --> K{.groupsの値は?}
    K -->|drop_last| L[最後のグループ削除]
    K -->|drop| M[全グループ削除]
    K -->|keep| N[グループ維持]
    K -->|rowwise| O[rowwise_df作成]
    L --> P[結果を返却]
    M --> P
    N --> P
    O --> P
    P --> Q[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 長さ1制約 | 各集計式は長さ1の値を返す必要がある | 常に適用 |
| BR-02 | .by/.groups排他 | .byと.groupsは同時に指定できない | 両方が指定された場合 |
| BR-03 | grouped_df時の.groups | デフォルトは"drop_last"で最後のグループが削除される | grouped_dfで.groups未指定 |
| BR-04 | rowwise_df時の.groups | デフォルトは"keep"でgrouped_dfに変換される | rowwise_dfで.groups未指定 |
| BR-05 | 変数の上書き | 同名の変数を定義すると上書きされる | 同名変数定義時 |
| BR-06 | 順次評価 | 集計式は順次評価され、先に定義した変数を後で参照可能 | data.frameバックエンド |

### 計算ロジック

**.groups引数の処理**:
```
if (.groups == "drop_last" && length(old_groups) > 1) {
  new_groups = old_groups[-length(old_groups)]
} else if (.groups == "keep") {
  new_groups = old_groups
} else if (.groups == "drop") {
  new_groups = NULL  # tibbleとして返却
} else if (.groups == "rowwise") {
  # rowwise_dfとして返却
}
```

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

該当なし（本機能はインメモリのデータフレーム操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | サイズエラー | 集計式が長さ1以外を返した場合 | "`{name}` must be size 1, not {actual_size}. To return more or less than 1 row per group, use `reframe()`." |
| - | 引数エラー | .byと.groupsの両方が指定された場合 | "Can't supply both `.by` and `.groups`." |
| - | 型エラー | 集計式がベクトルでない場合 | "`{name}` must be a vector, not {type}." |
| - | NULL混在エラー | グループ間でNULLと非NULLの結果が混在 | "Can't combine NULL and non NULL results." |

### リトライ仕様

該当なし（インタラクティブな関数呼び出しのため）

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

該当なし（本機能はデータベーストランザクションを使用しない）

## パフォーマンス要件

- 計算量はO(n * m)（n=行数、m=グループ数）
- グループごとに集計式を評価するため、グループ数が多いと処理時間が増加
- メモリ使用量は出力データサイズ（グループ数 * 集計列数）に比例

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

- 本機能は純粋なデータ変換操作であり、特別なセキュリティ考慮事項はない
- 入力データの機密性は集計後も保持される場合があるため、出力の取り扱いに注意

## 備考

- `summarise()`と`summarize()`はシノニム（同一機能）
- dplyr 1.1.0で`.by`引数が追加され、一時的なグループ化が可能に
- 長さ1以外を返したい場合は`reframe()`を使用
- データフレームバックエンドでは変数の順次参照が可能（他のバックエンドでは非対応の場合あり）

---

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

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

### 推奨読解順序

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

`summarise()`は入力データのグループ構造に基づいて出力を生成する。内部ではDataMaskを使用してデータアクセスを管理する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | data-mask.R | `R/data-mask.R` | DataMaskクラスの構造と役割 |
| 1-2 | group-data.R | `R/group-data.R` | グループデータの構造 |

**読解のコツ**: `summarise()`はDataMaskを通じて各グループのデータに効率的にアクセスする。グループごとに式を評価し、結果を収集する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | summarise.R | `R/summarise.R` | `summarise()`関数のジェネリック定義（106-114行目） |
| 2-2 | summarise.R | `R/summarise.R` | `summarise.data.frame()`（120-137行目） |
| 2-3 | summarise.R | `R/summarise.R` | `summarise.grouped_df()`（140-175行目） |
| 2-4 | summarise.R | `R/summarise.R` | `summarise.rowwise_df()`（178-207行目） |

**主要処理フロー**:
1. **107-111行目**: `.by`と`.groups`の排他チェック
2. **121行目**: `compute_by()`でグループ情報取得
3. **123行目**: `summarise_cols()`で集計式評価
4. **124行目**: `summarise_build()`で出力構築

#### Step 3: 集計処理の詳細を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | summarise.R | `R/summarise.R` | `summarise_cols()`関数（209-343行目） |
| 3-2 | summarise.R | `R/summarise.R` | `summarise_eval_one()`関数（345-376行目） |
| 3-3 | summarise.R | `R/summarise.R` | `summarise_build()`関数（378-385行目） |

**主要処理フロー（summarise_cols）**:
- **212-213行目**: DataMaskの作成
- **231-281行目**: 各式の評価ループ
- **283-286行目**: 長さ1チェック（summariseの場合）
- **335-338行目**: 結果をcolsに格納

#### Step 4: エラーメッセージ生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | summarise.R | `R/summarise.R` | `summarise_bullets`メソッド（387-453行目） |

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

```
summarise(.data, ..., .by, .groups)
    │
    ├─ UseMethod("summarise")
    │      │
    │      ├─ summarise.data.frame()
    │      │      │
    │      │      ├─ compute_by() [グループ取得]
    │      │      │
    │      │      ├─ summarise_cols()
    │      │      │      │
    │      │      │      ├─ DataMask$new()
    │      │      │      │
    │      │      │      ├─ expand_across() [across展開]
    │      │      │      │
    │      │      │      ├─ summarise_eval_one()
    │      │      │      │      │
    │      │      │      │      └─ mask$eval_all_summarise()
    │      │      │      │
    │      │      │      └─ dplyr_summarise_check_all_size_one() [長さチェック]
    │      │      │
    │      │      └─ summarise_build()
    │      │             │
    │      │             └─ dplyr_col_modify()
    │      │
    │      ├─ summarise.grouped_df()
    │      │      │
    │      │      └─ (同上 + .groups処理)
    │      │
    │      └─ summarise.rowwise_df()
```

### データフロー図

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

.data ─────────────────┬─ compute_by() ────────────────── グループ情報(by)
                       │         │
... (集計式) ──────────┤         │
                       │         ▼
.by (オプション) ──────┤   summarise_cols()
                       │         │
.groups (オプション) ──┘         ├─ DataMask作成
                                 │
                                 ├─ 式の評価
                                 │
                                 └─ 長さ1チェック
                                         │
                                         ▼
                                 summarise_build()
                                         │
                                         ▼
                            [集約されたdata.frame/grouped_df]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| summarise.R | `R/summarise.R` | ソース | summarise関数のメイン実装 |
| data-mask.R | `R/data-mask.R` | ソース | DataMaskクラス（式評価の基盤） |
| context.R | `R/context.R` | ソース | n()、cur_group()などのコンテキスト関数 |
| across.R | `R/across.R` | ソース | across()関数（複数列集計） |
| test-summarise.R | `tests/testthat/test-summarise.R` | テスト | summariseのユニットテスト |
