# 通知設計書 17-述語適用の100行制限

## 概要

本ドキュメントは、dplyrパッケージのcolwise関数群（`_if`バリアント）において、lazy dataframe（`tbl_lazy`など）に対して述語関数を適用する際に、最初の100行のみが評価対象となることを通知する情報メッセージの設計を記載する。

### 本通知の処理概要

`_if`バリアントの関数（`summarise_if()`, `mutate_if()`, `filter_if()`など）では、述語関数（predicate）を使用して操作対象の列を選択する。通常のデータフレームでは全データに述語を適用するが、遅延評価されるデータフレーム（例：dbplyr経由のデータベース接続）では、パフォーマンスのため最初の100行のみに述語を適用する。

**業務上の目的・背景**：データベース等のlazy dataframeに対して述語を適用する場合、全データを取得して評価すると非常に時間がかかる可能性がある。そのため、最初の100行のみで列の型を判定し、効率化を図る。ただし、この制限によりまれに意図しない列選択が発生する可能性があるため、ユーザーに通知する。

**通知の送信タイミング**：`tbl_ptype.default()`メソッド内で、入力が`tbl_lazy`クラスを継承している場合に通知が発生する。具体的には、`_if`バリアントの内部で列選択を行う際に呼び出される。

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

**通知内容の概要**：「Applying predicate on the first 100 rows」という固定メッセージが表示される。

**期待されるアクション**：ユーザーはこの制限を理解し、列選択が正しく行われているか確認する。必要に応じて、明示的に列を指定する`_at`バリアントを使用するか、`across()`への移行を検討する。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

R言語の標準メッセージハンドラを通じてコンソールに出力される。`suppressMessages()`で抑制可能。

## 通知テンプレート

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

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

### 本文テンプレート

```
Applying predicate on the first 100 rows
```

### 添付ファイル

該当なし

## テンプレート変数

該当なし（固定メッセージ）

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 関数呼び出し | `_if`バリアントの実行（`summarise_if()`等） | 入力が`tbl_lazy`を継承している | `inherits(.data, "tbl_lazy")`がTRUE |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 入力が通常のdata.frameの場合 | 全データに述語を適用するため |
| `tbl_ptype()`メソッドがオーバーライドされている場合 | カスタム実装により異なる動作 |
| `suppressMessages()`でラップされている場合 | ユーザーが明示的にメッセージを抑制 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[summarise_if等の実行] --> B[tbl_if_vars呼び出し]
    B --> C[tbl_ptype呼び出し]
    C --> D[tbl_ptype.default]
    D --> E{tbl_lazyを継承しているか}
    E -->|Yes| F[inform関数で通知]
    F --> G[collect n=100で100行取得]
    G --> H[述語関数を適用]
    E -->|No| I[そのままデータを使用]
    I --> H
    H --> J[列選択結果を返す]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| データベーステーブル | 最初の100行を取得 | `collect(.data, n = 100)` |

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

該当なし（動的に決定される）

### 更新テーブル一覧

該当なし（読み取り専用）

## エラー処理

### エラーケース一覧

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

### リトライ仕様

該当なし

## 配信設定

### レート制限

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

### 配信時間帯

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

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

特になし（固定メッセージのみ）。

## 備考

- `tbl_ptype()`はジェネリック関数で、パッケージがカスタム実装を提供可能
- コメントに「TODO: remove once moved to dplyr」とあり、将来的な変更が予定されている可能性がある
- dbplyr等のバックエンドでは、異なる`tbl_ptype()`実装を提供している可能性がある

---

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

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

### 推奨読解順序

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

`tbl_lazy`は遅延評価されるデータフレームで、dbplyrなどで使用される。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | colwise.R | `R/colwise.R` | 286-308行目の`tbl_ptype()`関数と関連コメント |

**読解のコツ**: `tbl_ptype()`は列の型情報を取得するために使用され、遅延評価データフレームでは効率のため制限がある。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | colwise.R | `R/colwise.R` | 196-267行目の`tbl_if_vars()`関数 |

**主要処理フロー**:
1. **226行目**: `.tbl <- tbl_ptype(.tbl)`でデータの型情報を取得
2. **244-264行目**: 述語関数を各列に適用して選択

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | colwise.R | `R/colwise.R` | 295-308行目の`tbl_ptype.default()`メソッド |

**主要処理フロー**:
- **300-301行目**: `tbl_lazy`を継承しているかチェック
- **303行目**: `inform("Applying predicate on the first 100 rows")`で通知
- **304行目**: `collect(.data, n = 100)`で最初の100行を取得

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

```
summarise_if(.tbl, .predicate, .funs, ...)
    │
    ├─ manip_if()
    │      │
    │      └─ tbl_if_vars()                 # 列選択
    │             │
    │             ├─ tbl_ptype()            # 型情報取得
    │             │      │
    │             │      └─ tbl_ptype.default()
    │             │             │
    │             │             ├─ inherits(.data, "tbl_lazy")
    │             │             │
    │             │             ├─ inform()  # 通知(本通知)
    │             │             │
    │             │             └─ collect(.data, n = 100)
    │             │
    │             └─ [述語関数を適用]
    │
    └─ summarise(.tbl, !!!funs)
```

### データフロー図

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

.tbl (tbl_lazy) ─────┐
                     │
.predicate (関数) ───┼──▶ summarise_if() ──▶ 結果(tbl_lazy)
                     │         │
.funs (関数) ────────┘         │
                               ├─▶ tbl_if_vars()
                               │        │
                               │        └─▶ tbl_ptype()
                               │                 │
                               │                 ▼
                               │           [コンソール通知]
                               │           "Applying predicate on the first 100 rows"
                               │                 │
                               │                 ▼
                               │           collect(n=100)
                               │                 │
                               │                 ▼
                               │           [述語を適用して列選択]
                               │
                               └─▶ summarise()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| colwise.R | `R/colwise.R` | ソース | tbl_ptype()、tbl_if_vars()の実装 |
| colwise-mutate.R | `R/colwise-mutate.R` | ソース | summarise_if()等の実装 |
