# 機能設計書 1-filter

## 概要

本ドキュメントは、dplyrパッケージの`filter`関数に関する機能設計書です。`filter`関数は、論理条件に基づいてデータフレームの行をフィルタリングする機能を提供します。

### 本機能の処理概要

`filter`関数は、指定された論理条件を評価し、その条件が`TRUE`となる行のみを保持するデータフレーム操作関数です。複数の条件を指定した場合は、それらが`&`演算子で結合され、すべての条件を満たす行のみが抽出されます。

**業務上の目的・背景**：データ分析において、特定の条件を満たすデータのみを抽出することは最も基本的かつ頻繁に行われる操作です。`filter`関数は、SQLのWHERE句に相当する機能を提供し、大規模なデータセットから必要なデータを効率的に抽出することを可能にします。ベースRの`subset`関数や`[`演算子と比較して、より直感的で可読性の高いコードを書くことができます。

**機能の利用シーン**：
- 特定の条件を満たす顧客データの抽出（例：年齢が30歳以上の顧客）
- 外れ値や異常値の除外
- 期間を指定したデータの抽出（例：2024年のデータのみ）
- カテゴリ変数による絞り込み（例：特定の地域のデータ）

**主要な処理内容**：
1. 引数のバリデーション（`.by`と`.preserve`の同時指定チェック等）
2. quosureの作成と条件式の展開（`across`や`pick`のサポート）
3. グループ化情報の計算（`.by`引数または既存のグループ化を使用）
4. データマスク環境でのフィルタ条件の評価
5. 条件を満たす行インデックスの計算
6. `dplyr_row_slice`による行の抽出

**関連システム・外部連携**：
- tidyselect: 列選択機能との連携
- vctrs: ベクトル操作基盤
- rlang: quosureとデータマスキング機能

**権限による制御**：該当なし（Rライブラリのため）

## 関連画面

本プロジェクトはRライブラリ（dplyr）であり、ユーザーインターフェース画面は存在しません。

## 機能種別

データ操作（行のフィルタリング）/ データ変換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| .data | data.frame | Yes | フィルタリング対象のデータフレーム | data.frameまたはその派生クラス |
| ... | expressions | No | 論理値を返す条件式（複数指定可能） | 論理ベクトルを返す式であること |
| .by | tidy-select | No | 一時的なグループ化に使用する列 | データ内に存在する列であること |
| .preserve | logical | No | グループ構造を保持するか（デフォルト: FALSE） | `.by`と同時指定不可 |

### 入力データソース

- メモリ上のdata.frame、tibble、grouped_df、rowwise_df

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | .dataと同じ型 | フィルタリングされたデータフレーム |

### 出力先

- 関数の戻り値として返却（メモリ上）

## 処理フロー

### 処理シーケンス

```
1. 引数バリデーション
   └─ check_by_typo(): ...引数内の.byタイポをチェック
   └─ check_not_both_by_and_preserve(): .byと.preserveの同時指定をチェック
2. ジェネリック関数のディスパッチ
   └─ UseMethod("filter")でクラスに応じたメソッドを呼び出し
3. filter_impl()の実行
   └─ dplyr_quosures()で条件式をquosureに変換
   └─ check_filter()で名前付き引数のバリデーション
   └─ compute_by()でグループ化情報を計算
4. filter_rows()の実行
   └─ DataMask$new()でデータマスクを作成
   └─ filter_expand()で条件式を展開（across等のサポート）
   └─ filter_eval()で条件を評価し、行インデックスを計算
5. dplyr_row_slice()で行を抽出
   └─ preserveフラグに応じてグループ構造を再計算
```

### フローチャート

```mermaid
flowchart TD
    A[filter開始] --> B{引数バリデーション}
    B -->|エラー| E1[エラー終了]
    B -->|OK| C[UseMethod dispatch]
    C --> D[filter.data.frame]
    D --> F[filter_impl]
    F --> G[quosure作成]
    G --> H[グループ化計算]
    H --> I[DataMask作成]
    I --> J[条件式展開]
    J --> K[条件評価]
    K --> L{条件結果の検証}
    L -->|型エラー| E2[エラー終了]
    L -->|サイズエラー| E3[エラー終了]
    L -->|OK| M[行インデックス計算]
    M --> N[dplyr_row_slice]
    N --> O[結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | NA値の扱い | NAはFALSEとして扱われ、条件がNAの行は除外される | 常時 |
| BR-02 | 複数条件の結合 | カンマ区切りの複数条件は&演算子で結合される | 複数条件指定時 |
| BR-03 | グループ内評価 | グループ化されたデータでは条件がグループ内で評価される | grouped_df使用時 |
| BR-04 | 行順序の保持 | 出力行は入力と同じ順序で出現する | 常時 |

### 計算ロジック

- 条件式は各行に対してベクトル化評価される
- 複数条件: `cond1 & cond2 & ... & condN`として結合
- `when_any()`でラップした場合: `cond1 | cond2 | ... | condN`として結合

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | dplyr:::filter_incompatible_type | 条件式が論理ベクトル以外を返した場合 | 条件式を論理値を返すよう修正 |
| - | dplyr:::filter_incompatible_size | 条件式の結果サイズが行数と一致しない場合 | 条件式を修正 |
| - | abort | .byと.preserveを同時指定した場合 | どちらか一方のみ指定 |
| - | abort | 名前付き引数で=を==と間違えた場合 | ==演算子を使用 |

### リトライ仕様

該当なし（同期処理のため）

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

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

## パフォーマンス要件

- 大規模データセットに対しても効率的に動作するよう、C++バックエンド（vctrs）を使用
- グループ化データでは並列評価は行わない（グループ数に応じて線形時間）

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

- 入力データの検証はdplyrフレームワーク内で実施
- 外部入力を条件式に直接使用する場合は、インジェクション攻撃に注意

## 備考

- `filter_out`関数は`filter`の逆操作として同一ファイルで定義されている
- dplyr 1.1.0以降、1列行列の使用は非推奨警告が出る

---

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

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

### 推奨読解順序

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

まず、filter関数で使用される主要なデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | data-mask.R | `R/data-mask.R` | DataMaskクラスの構造と役割を理解する |
| 1-2 | generics.R | `R/generics.R` | dplyr_row_sliceなどの汎用関数を理解する |

**読解のコツ**: R6クラスであるDataMaskはdplyrの中核的なデータ構造である。`private`メンバーに格納されるrows, chops, keysなどの意味を把握することが重要。

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

処理の起点となる関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | filter.R | `R/filter.R` | filter関数のエントリーポイント |

**主要処理フロー**:
1. **216-220行目**: filter関数定義。引数チェック後UseMethodでディスパッチ
2. **231-239行目**: filter.data.frameメソッド。filter_implを呼び出す
3. **252-283行目**: filter_impl関数。実際のフィルタ処理の実装

#### Step 3: 条件評価の詳細を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | filter.R | `R/filter.R` | filter_rows, filter_expand, filter_eval関数 |

**主要処理フロー**:
- **285-311行目**: filter_rows関数。DataMaskを作成し条件を評価
- **334-354行目**: filter_expand関数。across/pick/if_anyなどを展開
- **359-402行目**: filter_eval関数。マスク環境で条件を評価しインデックスを返す

#### Step 4: 行抽出の実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | generics.R | `R/generics.R` | dplyr_row_slice関数の実装 |

**主要処理フロー**:
- **101-107行目**: dplyr_row_slice汎用関数
- **110-112行目**: data.frame向け実装。vec_sliceとdplyr_reconstructを使用
- **115-131行目**: grouped_df向け実装。グループ構造の再計算を含む

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

```
filter(.data, ..., .by, .preserve)
    │
    ├─ check_by_typo(...)
    ├─ check_not_both_by_and_preserve(.by, .preserve)
    └─ UseMethod("filter")
           │
           └─ filter.data.frame(.data, ..., .by, .preserve)
                  │
                  └─ filter_impl(.data, ..., .by, .preserve, .verb="filter")
                         │
                         ├─ dplyr_quosures(...)
                         ├─ check_filter(dots)
                         ├─ compute_by(.by, .data)
                         ├─ filter_rows(data, dots, by, verb)
                         │      │
                         │      ├─ DataMask$new(data, by, verb)
                         │      ├─ filter_expand(dots, mask)
                         │      │      └─ expand_pick(), expand_if_across()
                         │      └─ filter_eval(dots, dots_expanded, invert, mask)
                         │             └─ mask$eval_all_filter(dots_expanded, invert, env_filter)
                         │
                         └─ dplyr_row_slice(.data, loc, preserve)
```

### データフロー図

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

.data (data.frame)  ───▶ DataMask作成 ───▶ 条件評価 ───▶ 行インデックス
      │                       │                  │              │
      │                       ▼                  │              ▼
      │                  グループ情報            │         loc (integer)
      │                       │                  │              │
      └───────────────────────┴──────────────────┴──────────────┘
                                                                │
                                                                ▼
                                                      dplyr_row_slice
                                                                │
                                                                ▼
                                                        結果data.frame
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| filter.R | `R/filter.R` | ソース | filter/filter_out関数の実装 |
| data-mask.R | `R/data-mask.R` | ソース | DataMaskクラスの定義 |
| generics.R | `R/generics.R` | ソース | dplyr_row_slice等の汎用関数 |
| groups-with.R | `R/groups-with.R` | ソース | compute_by関数の実装 |
| colwise.R | `R/colwise.R` | ソース | across関連の実装 |
| when.R | `R/when.R` | ソース | when_any/when_all関数の実装 |
| error.R | `R/error.R` | ソース | エラーハンドリング |
| conditions.R | `R/conditions.R` | ソース | 警告・エラー条件 |
