# 通知設計書 14-summarise結果のグループ化通知

## 概要

本ドキュメントは、dplyrパッケージの`summarise()`関数において、グループ化されたデータフレームに対して集計を行った後の結果のグループ構造について通知する情報メッセージの設計を記載する。

### 本通知の処理概要

`summarise()`関数は、データフレームの各グループを1行に要約する機能を提供する。複数のグループ変数でグループ化されている場合、デフォルトでは最後のグループ変数が削除され（"drop_last"）、結果は残りのグループ変数でグループ化される。

**業務上の目的・背景**：`summarise()`の結果のグループ構造は、後続の処理に影響を与える重要な情報である。ユーザーが意図しないグループ構造のまま処理を続けることを防ぐため、結果のグループ構造を明示的に通知する。これにより、パイプラインでの予期しない動作を防ぎ、コードの正確性を向上させる。

**通知の送信タイミング**：`summarise()`関数がgrouped_dfまたはrowwise_dfに対して実行され、`.groups`引数が指定されていない場合に通知が発生する。具体的には、`summarise_verbose()`関数がTRUEを返し、かつ結果がグループ化されている場合に通知される。

**通知の受信者**：R言語のコンソールを使用している開発者・データアナリスト。通知はコンソールに直接出力される。

**通知内容の概要**：grouped_dfの場合は「`summarise()` has regrouped the output.」で始まり、元のグループ変数、結果のグループ変数、抑制方法が案内される。rowwise_dfの場合は「`summarise()` has converted the output from a rowwise data frame to a grouped data frame.」と表示される。

**期待されるアクション**：ユーザーは通知を確認し、結果のグループ構造が意図したものか確認する。必要に応じて`.groups`引数を明示的に指定するか、`.by`引数を使用した操作単位のグループ化を検討する。

## 通知種別

コンソール情報メッセージ（`inform()`による`message`条件）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（関数実行中に即座に表示） |
| 優先度 | 低（情報通知） |
| リトライ | 無し |

### 送信先決定ロジック

R言語の標準メッセージハンドラを通じてコンソールに出力される。`suppressMessages()`で抑制可能。また、`options(dplyr.summarise.inform = FALSE)`で抑制可能。

## 通知テンプレート

### コンソール出力の場合

| 項目 | 内容 |
|-----|------|
| 形式 | テキスト（cli形式） |

### 本文テンプレート（grouped_dfの場合）

```
`summarise()` has regrouped the output.
i Summaries were computed grouped by {元のグループ変数}.
i Output is grouped by {結果のグループ変数}.
i Use `summarise(.groups = "drop_last")` to silence this message.
i Use `summarise(.by = c(...))` for per-operation grouping instead.
```

### 本文テンプレート（rowwise_dfの場合）

```
`summarise()` has converted the output from a rowwise data frame to a grouped data frame.
i Summaries were computed rowwise.
i Output is grouped by {グループ変数}.
i Use `summarise(.groups = "keep")` to silence this message.
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| old_groups | 元のグループ変数名 | `by$names` | Yes |
| new_groups | 結果のグループ変数名 | `old_groups[-n]`（最後を除く） | Yes（grouped_dfの場合） |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 関数呼び出し | `summarise()`の実行（grouped_dfに対して） | `.groups`引数が未指定かつグループ数が2以上 | デフォルトの"drop_last"動作時 |
| 関数呼び出し | `summarise()`の実行（rowwise_dfに対して） | `.groups`引数が未指定かつグループ変数がある | デフォルトの"keep"動作時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| `.groups`引数が明示的に指定されている場合 | ユーザーが意図的にグループ構造を指定 |
| `options(dplyr.summarise.inform = FALSE)`が設定されている場合 | グローバルオプションで抑制 |
| グループ変数が1つ以下の場合 | 結果がグループ化されないため |
| パッケージ内の関数から呼び出された場合 | `topenv(.env)`がglobal_envでない場合 |
| `suppressMessages()`でラップされている場合 | ユーザーが明示的にメッセージを抑制 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[summarise実行] --> B{grouped_df または rowwise_df か}
    B -->|Yes| C[summarise_verbose呼び出し]
    B -->|No| D[通知なしで処理]
    C --> E{.groupsが指定されているか}
    E -->|Yes| D
    E -->|No| F{dplyr.summarise.informオプション}
    F -->|FALSE| D
    F -->|TRUE/NULL| G{グローバル環境から呼び出しか}
    G -->|No| D
    G -->|Yes| H{グループ数が2以上か/rowwiseでグループ変数があるか}
    H -->|No| D
    H -->|Yes| I[inform関数で通知]
    I --> J[結果を返す]
    D --> J
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| 該当なし | - | インメモリデータフレーム操作 |

### テーブル別参照項目詳細

該当なし（データベースは使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 該当なし | - | この通知自体はエラーではなく情報提供 |

### リトライ仕様

該当なし

## 配信設定

### レート制限

該当なし（即座に1回表示）

### 配信時間帯

該当なし（関数実行時に即座に表示）

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

グループ変数名情報がコンソールに出力されるため、機密性の高い変数名が含まれる場合は注意が必要。

## 備考

- `.groups`引数のオプション: "drop_last"（デフォルト for grouped_df）、"drop"、"keep"（デフォルト for rowwise_df）、"rowwise"
- dplyr 1.0.0で導入された`.by`引数を使用すると、操作単位のグループ化が可能で、この通知を回避できる
- `summarize()`は`summarise()`のエイリアスで、同じ通知が発生する

---

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

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

### 推奨読解順序

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

summarise()は入力のグループ構造に応じて異なる結果を返す。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | summarise.R | `R/summarise.R` | 1-105行目のドキュメントでsummarise()の概要と.groups引数を理解 |

**読解のコツ**: .groups引数の各オプション（"drop_last", "drop", "keep", "rowwise"）の違いを理解することが重要。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | summarise.R | `R/summarise.R` | 106-114行目の`summarise()`ジェネリック関数 |
| 2-2 | summarise.R | `R/summarise.R` | 140-175行目の`summarise.grouped_df()`メソッド |
| 2-3 | summarise.R | `R/summarise.R` | 178-207行目の`summarise.rowwise_df()`メソッド |

**主要処理フロー**:
1. **140-145行目**: grouped_dfの場合、`compute_by()`と`summarise_cols()`で集計実行
2. **146行目**: `summarise_verbose()`で通知を出すべきか判定
3. **148-175行目**: `.groups`に応じたグループ構造の設定と通知

#### Step 3: 通知ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | summarise.R | `R/summarise.R` | 457-471行目の`summarise_verbose()`関数 |
| 3-2 | summarise.R | `R/summarise.R` | 473-485行目の`inform_implicit_drop_last_for_grouped_df()`関数 |
| 3-3 | summarise.R | `R/summarise.R` | 487-494行目の`inform_implicit_keep_for_rowwise_df()`関数 |

**主要処理フロー**:
- **457-471行目**: `.groups`が指定されているか、オプションが設定されているか、グローバル環境からの呼び出しかを判定
- **473-485行目**: grouped_dfの場合の通知メッセージを構築（cli形式）
- **487-494行目**: rowwise_dfの場合の通知メッセージを構築（cli形式）

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

```
summarise(.data, ..., .by, .groups)
    │
    ├─ summarise.grouped_df()
    │      │
    │      ├─ compute_by()                  # グループ情報の計算
    │      │
    │      ├─ summarise_cols()              # 集計処理
    │      │
    │      ├─ summarise_build()             # 結果の構築
    │      │
    │      ├─ summarise_verbose()           # 通知判定
    │      │      ├─ getOption("dplyr.summarise.inform")
    │      │      └─ is_reference(topenv(.env), global_env())
    │      │
    │      └─ inform_implicit_drop_last_for_grouped_df()  # 通知(本通知)
    │             └─ cli_format_each_inline()
    │             └─ inform()
    │
    └─ summarise.rowwise_df()
           │
           ├─ [同様の処理]
           │
           └─ inform_implicit_keep_for_rowwise_df()  # 通知(本通知)
                  └─ cli_format_each_inline()
                  └─ inform()
```

### データフロー図

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

.data (grouped_df) ───┐
                      │
... (集計式) ─────────┼──▶ summarise.grouped_df() ──▶ 結果(grouped_df/tibble)
                      │           │
.groups (NULL) ───────┘           │
                                  ├─▶ summarise_cols()
                                  │
                                  ├─▶ summarise_verbose()
                                  │        │
                                  │        ▼
                                  │   [通知判定]
                                  │
                                  └─▶ inform_implicit_drop_last_for_grouped_df()
                                            │
                                            ▼
                                  [コンソール通知]
                    "`summarise()` has regrouped the output. ..."
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| summarise.R | `R/summarise.R` | ソース | summarise()関数と関連ヘルパーの実装 |
| group-by.R | `R/group-by.R` | ソース | group_by()関数の実装 |
| grouped-df.R | `R/grouped-df.R` | ソース | grouped_dfクラスの定義 |
| rowwise.R | `R/rowwise.R` | ソース | rowwise_dfクラスの定義 |
