# 機能設計書 46-case_match

## 概要

本ドキュメントは、dplyrパッケージの`case_match()`関数の機能設計について記述する。`case_match()`は値のマッチングに基づく条件分岐を提供する関数であるが、dplyr 1.2.0で非推奨となり、`recode_values()`への移行が推奨されている。

### 本機能の処理概要

`case_match()`は、入力ベクトル`.x`の各値を指定したパターンと照合し、一致した場合に対応する値を返すベクトル化された条件分岐関数である。これはR標準の`switch()`文のベクトル化版であり、SQLのCASE文に類似している。各ケースは順次評価され、最初に一致したパターンの値が使用される。一致しない場合は`.default`の値が使用される。

**注意**：この関数はdplyr 1.2.0で非推奨（deprecated）となった。より強力で直感的な名前を持つ`recode_values()`および`replace_values()`の使用が推奨される。

**業務上の目的・背景**：データのカテゴリ変換やコードの再マッピングは、データ分析の前処理で頻繁に発生する作業である。`case_when()`は論理条件に基づく分岐に適しているが、単純な値のマッチングには冗長になりがちである。`case_match()`（および後継の`recode_values()`）は、値ベースのマッピングを簡潔に記述できる。

**機能の利用シーン**：
- カテゴリコードの変換（例：1, 2, 3を"A", "B", "C"に変換）
- 値のグループ化（例：複数の値を1つのカテゴリにまとめる）
- ルックアップテーブルによる値の変換

**主要な処理内容**：
1. フォーミュラを解析してLHS（パターン）とRHS（値）を抽出する
2. LHSを`.x`の型にキャストする
3. `.x`の各要素をLHSパターンと照合する
4. 一致した場合は対応するRHS値を返す
5. 一致しない場合は`.default`値を返す

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

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

## 関連画面

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

## 機能種別

計算処理 / データ変換 / 条件分岐（非推奨）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| .x | any | Yes | マッチング対象のベクトル | ベクトルであること |
| ... | formula | Yes | `pattern ~ value`形式の二項フォーミュラ | 少なくとも1つのフォーミュラが必要 |
| .default | any | No | どのパターンにも一致しない場合のデフォルト値（デフォルト: NULL = NA） | RHSと共通型を持つこと |
| .ptype | any | No | 出力型を指定するプロトタイプ | 有効な型であること |

### 入力データソース

関数の引数として直接渡されるベクトルとフォーミュラ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | any | .xと同じサイズで、RHS入力と.defaultの共通型を持つベクトル |

### 出力先

呼び出し元に返される。

## 処理フロー

### 処理シーケンス

```
1. 非推奨警告の出力
   └─ lifecycle::deprecate_soft()で警告を出力
2. フォーミュラの解析
   └─ eval_formulas()で...を解析
   └─ LHS（haystacks）とRHS（values）を分離
3. vec_case_match()の呼び出し
   └─ .x, haystacks, values, .default, .ptypeを渡す
4. 内部処理
   └─ haystacksを.xの型にキャスト
   └─ vec_in()で各haystackと.xを照合
   └─ vec_case_when()で条件に基づいて値を選択
5. 結果ベクトルを返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始: case_match呼び出し] --> B[非推奨警告を出力]
    B --> C[eval_formulas で...を解析]
    C --> D{...が空か?}
    D -->|Yes| E[エラー: ... can't be empty]
    D -->|No| F[LHSとRHSを分離]
    F --> G[vec_case_match を呼び出し]
    G --> H[haystacksを.xの型にキャスト]
    H --> I[各haystackと.xをvec_in()で照合]
    I --> J[vec_case_when で値を選択]
    J --> K[結果ベクトルを返す]
    E --> L[終了]
    K --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-46-01 | 非推奨 | dplyr 1.2.0で非推奨。recode_values()を使用すること | 常に適用 |
| BR-46-02 | 型キャスト | LHS（パターン）は.xの型にキャストされる | 常に適用 |
| BR-46-03 | 順次評価 | パターンは上から順に評価され、最初に一致したパターンが使用される | 常に適用 |
| BR-46-04 | 複数値パターン | LHSに複数の値を指定可能（例：c(1, 2) ~ "AB"） | 常に適用 |

### 計算ロジック

```
conditions = map(haystacks, function(haystack) vec_in(.x, haystack))
vec_case_when(conditions, values, default = .default, ptype = .ptype, size = length(.x))
```

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 非推奨警告 | 関数呼び出し時 | recode_values()に移行する |
| - | 引数エラー | ...が空の場合 | 少なくとも1つのフォーミュラを渡す |
| - | 型エラー | LHSが.xの型にキャストできない場合 | 互換性のある値を使用する |

### リトライ仕様

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

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

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

## パフォーマンス要件

- vctrsの効率的な実装を活用すること

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

特になし

## 備考

- **非推奨**：dplyr 1.2.0で非推奨となった。`recode_values()`への移行を推奨
- `recode_values()`は追加の`unmatched`引数を持ち、より安全なコードが書ける
- `recode_values()`は`from`/`to`引数でルックアップテーブルを直接使用できる

---

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

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

### 推奨読解順序

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

`case_match()`は非推奨関数であり、内部で`vec_case_match()`を呼び出す。

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

**読解のコツ**: 非推奨警告の処理と、`vec_case_match()`への委譲が主な処理である。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | case-match.R | `R/case-match.R` | 163-196行目の`case_match()`関数定義 |

**主要処理フロー**:
1. **164-169行目**: `lifecycle::deprecate_soft()`で非推奨警告を出力
2. **175行目**: `allow_empty_dots <- FALSE`
3. **177-180行目**: `eval_formulas()`でフォーミュラを解析
4. **181-182行目**: LHS（haystacks）とRHS（values）を取得
5. **184-196行目**: `vec_case_match()`を呼び出し

#### Step 3: vec_case_match()を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | case-match.R | `R/case-match.R` | 198-239行目の`vec_case_match()`関数 |

**主要処理フロー**:
- **217-222行目**: haystacksを.xの型にキャスト
- **224行目**: `vec_in()`で各haystackと.xを照合してconditionsを生成
- **228-238行目**: `vec_case_when()`を呼び出し

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

```
case_match(.x, ..., .default, .ptype)
    │
    ├─ lifecycle::deprecate_soft() [非推奨警告]
    │
    ├─ eval_formulas(...)
    │      ├─ validate_and_split_formula()
    │      └─ eval_tidy() [LHS/RHSの評価]
    │
    └─ vec_case_match()
           ├─ vec_cast_common() [haystacksを.xの型にキャスト]
           ├─ map(vec_in) [条件生成]
           └─ vec_case_when() [値選択]
```

### データフロー図

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

.x (ベクトル)      ───▶  マッチング対象として保持    ───▶  needles

...フォーミュラ    ───▶  eval_formulas()で解析      ───▶  haystacks, values
  (pattern ~ value)

haystacks          ───▶  vec_cast_common()で        ───▶  キャスト済みhaystacks
                         .xの型にキャスト

needles +          ───▶  vec_in()で各haystackと     ───▶  conditions
  haystacks              照合

conditions +       ───▶  vec_case_when()で          ───▶  結果ベクトル
  values + default       値を選択
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| case-match.R | `R/case-match.R` | ソース | `case_match()`関数の実装（非推奨） |
| recode-values.R | `R/recode-values.R` | ソース | `recode_values()`関数（推奨される後継機能） |
| case-when.R | `R/case-when.R` | ソース | `eval_formulas()`などの共通関数 |
