# 機能設計書 43-if_else

## 概要

本ドキュメントは、dplyrパッケージの`if_else()`関数の機能設計について記述する。`if_else()`はベクトル化されたif-else条件分岐を提供し、base Rの`ifelse()`と比較して型の厳密性と欠損値の明示的な処理を特徴とする。

### 本機能の処理概要

`if_else()`は、論理条件ベクトルに基づいて、条件が`TRUE`の場合は`true`引数の値を、`FALSE`の場合は`false`引数の値を返すベクトル化された条件分岐関数である。base Rの`ifelse()`と異なり、`true`、`false`、`missing`の共通型を出力型として使用し、型の一貫性を保証する。また、条件が`NA`の場合の処理を`missing`引数で明示的に指定できる。

**業務上の目的・背景**：データ変換において条件に基づいて値を選択する処理は非常に頻繁に発生する。base Rの`ifelse()`は型の保持に問題があり（例：因子型が整数に変換される）、`NA`の処理も暗黙的である。`if_else()`はこれらの問題を解決し、型安全な条件分岐を提供することで、予期しないデータ型の変換やバグを防止する。

**機能の利用シーン**：
- `mutate()`内で条件に基づいて新しい列を作成する場合
- 二値分類（例：しきい値に基づく「高」「低」の分類）
- 条件付きの値の置換
- `NA`値の明示的な処理が必要な場合

**主要な処理内容**：
1. 条件ベクトルを評価する
2. `true`と`false`の値を条件のサイズにリサイクルする
3. `true`、`false`、`missing`の共通型を決定する
4. 条件に基づいて適切な値を選択する
5. 結果ベクトルを返す

**関連システム・外部連携**：vctrsパッケージの`vec_if_else()`を内部で使用する。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | 本プロジェクトはRライブラリであり、ユーザーインターフェース画面は存在しない |

## 機能種別

計算処理 / データ変換 / 条件分岐

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| condition | logical | Yes | 条件を表す論理ベクトル | 論理型であること |
| true | any | Yes | conditionがTRUEの場合に使用する値 | conditionのサイズにリサイクル可能であること |
| false | any | Yes | conditionがFALSEの場合に使用する値 | conditionのサイズにリサイクル可能であること |
| missing | any | No | conditionがNAの場合に使用する値（デフォルト: NULL = NA） | conditionのサイズにリサイクル可能であること |
| ... | - | No | 未使用（将来の互換性のため） | 空であること |
| ptype | any | No | 出力型を指定するプロトタイプ | 有効な型であること |
| size | integer | No | 非推奨。出力サイズの指定 | 使用しないこと |

### 入力データソース

関数の引数として直接渡されるベクトル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | any | conditionと同じサイズで、true/false/missingの共通型を持つベクトル |

### 出力先

呼び出し元に返される。

## 処理フロー

### 処理シーケンス

```
1. 引数の検証
   └─ ...が空であることを確認
   └─ size引数が使用されている場合は非推奨警告を出力
2. vctrs::vec_if_else()を呼び出す
   └─ condition, true, false, missing, ptypeを渡す
3. vctrs内部での処理
   └─ true, false, missingを共通型にキャスト
   └─ conditionのサイズにリサイクル
   └─ 条件に基づいて値を選択
4. 結果ベクトルを返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始: if_else呼び出し] --> B{...が空か?}
    B -->|No| C[エラー: ... must be empty]
    B -->|Yes| D{size引数が使用されているか?}
    D -->|Yes| E[非推奨警告を出力]
    D -->|No| F[vctrs::vec_if_else を呼び出し]
    E --> F
    F --> G[共通型を決定]
    G --> H[リサイクル処理]
    H --> I{各要素を評価}
    I -->|condition == TRUE| J[true値を選択]
    I -->|condition == FALSE| K[false値を選択]
    I -->|condition == NA| L{missing が指定されているか?}
    L -->|Yes| M[missing値を選択]
    L -->|No| N[NA値を使用]
    J --> O[結果ベクトルを返す]
    K --> O
    M --> O
    N --> O
    C --> P[終了]
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-43-01 | 型の厳密性 | true、false、missingは共通型にキャストされる | 常に適用 |
| BR-43-02 | リサイクル規則 | true、falseはconditionのサイズにリサイクルされる | 常に適用 |
| BR-43-03 | NA条件の処理 | conditionがNAの場合、missingが指定されていればその値、なければNAを使用 | 常に適用 |
| BR-43-04 | 出力サイズ | 出力はconditionと同じサイズ | 常に適用 |

### 計算ロジック

```
for each i in 1:length(condition):
    if condition[i] == TRUE:
        result[i] = true[i]
    else if condition[i] == FALSE:
        result[i] = false[i]
    else:  # condition[i] == NA
        result[i] = missing[i] if missing is provided else NA
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | 本関数はインメモリ操作のみでデータベース操作を行わない |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 引数エラー | conditionが論理型でない場合 | 論理ベクトルを渡す |
| - | 型エラー | true/false/missingの共通型がない場合 | 互換性のある型を使用する |
| - | サイズエラー | リサイクルが不可能な場合 | 適切なサイズのベクトルを使用する |
| - | 非推奨警告 | size引数を使用した場合 | size引数を削除する |

### リトライ仕様

リトライは不要（即座にエラーを返す）

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

該当なし（インメモリ操作のみ）

## パフォーマンス要件

- vctrsの効率的な実装を活用すること
- 大規模ベクトルでも効率的に動作すること

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

特になし

## 備考

- `if_else()`はbase Rの`ifelse()`の改良版である
- dplyr 1.2.0でsize引数は非推奨となった
- 複数条件の場合は`case_when()`の使用を検討すること

---

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

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

### 推奨読解順序

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

`if_else()`はvctrsパッケージの`vec_if_else()`に委譲するシンプルな関数である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | if-else.R | `R/if-else.R` | `if_else()`関数の全体構造を理解する |

**読解のコツ**: dplyrの`if_else()`はvctrsの`vec_if_else()`への薄いラッパーである。主な付加価値は非推奨警告の処理とエラーコールの設定である。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | if-else.R | `R/if-else.R` | 56-83行目の`if_else()`関数定義 |

**主要処理フロー**:
1. **65行目**: `check_dots_empty0(...)` - ...引数が空であることを確認
2. **67-73行目**: size引数の非推奨警告処理
3. **75-82行目**: `vec_if_else()`の呼び出し
   - condition, true, false, missing, ptypeを渡す
   - error_callを現在の環境に設定

#### Step 3: ドキュメントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | if-else.R | `R/if-else.R` | 1-55行目のroxygenドキュメント |

**読解のコツ**: ドキュメントには`ifelse()`との違い、型の厳密性、`missing`引数の使い方が詳細に記載されている。

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

```
if_else(condition, true, false, missing, ptype)
    │
    ├─ check_dots_empty0(...) [引数検証]
    │
    ├─ lifecycle::deprecate_warn() [size引数の非推奨警告]
    │      └─ size引数が使用されている場合のみ
    │
    └─ vctrs::vec_if_else()
           ├─ vec_cast_common() [共通型へのキャスト]
           ├─ vec_recycle() [リサイクル処理]
           └─ [条件に基づく値の選択]
```

### データフロー図

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

condition       ───▶  vec_if_else() 内で評価      ───▶  選択インデックス
  (論理ベクトル)

true, false,    ───▶  共通型へキャスト            ───▶  キャスト済みベクトル
  missing             vec_cast_common()

キャスト済み    ───▶  conditionサイズに           ───▶  リサイクル済みベクトル
  ベクトル            リサイクル

選択インデックス ───▶ 条件に基づいて値を選択      ───▶  結果ベクトル
  + リサイクル済み
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| if-else.R | `R/if-else.R` | ソース | `if_else()`関数の実装 |
| case-when.R | `R/case-when.R` | ソース | `case_when()`関数（複数条件の場合の代替） |
| vctrs.R | `R/vctrs.R` | ソース | vctrsパッケージとの連携 |
