# 機能設計書 12-pull

## 概要

本ドキュメントは、dplyrパッケージの`pull()`関数に関する機能設計書である。この関数は、データフレームから単一の列をベクトルとして抽出するための機能を提供する。

### 本機能の処理概要

`pull()`関数は、データフレームから指定した列をベクトルとして取り出す関数である。Rの`$`演算子と同様の動作をするが、パイプライン内での使用に適しており、リモートデータフレーム（dbplyrなど）でも動作する。

**業務上の目的・背景**：データ分析のワークフローにおいて、データフレームの特定の列をベクトルとして取得する必要がある場面は多い。例えば、集計結果を他の関数に渡す場合や、特定の値のリストを作成する場合などである。`pull()`は、パイプライン構文と整合性のある形でこの操作を実現し、コードの可読性を向上させる。

**機能の利用シーン**：
- データフレームから単一の列をベクトルとして取得したい場合
- パイプライン処理の最後に特定の列の値を抽出したい場合
- 名前付きベクトルを作成したい場合（例：辞書的なマッピング）
- リモートデータソース（データベース）から列を取得したい場合

**主要な処理内容**：
1. `var`引数で指定された列を特定（正の整数、負の整数、または列名）
2. `tidyselect::vars_pull()`を使用して列名を解決
3. 指定された列をベクトルとして抽出
4. `name`引数が指定されている場合、別の列の値を名前として設定

**関連システム・外部連携**：tidyselectパッケージの`vars_pull()`関数に依存。dbplyrなどのリモートデータソースに対応するためのジェネリック関数として実装されている。

**権限による制御**：本機能はRパッケージの一部であり、特定の権限制御は存在しない。関数を呼び出す全てのユーザーが同じ機能を利用可能である。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | 本機能はRライブラリ（dplyr）のため画面は存在しない |

## 機能種別

データ抽出処理（列操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| .data | data.frame | Yes | 操作対象のデータフレーム | data.frameまたはその派生クラスであること |
| var | integer/character | No | 抽出する列の指定。デフォルトは-1（最後の列） | 有効な列インデックスまたは列名 |
| name | character | No | 結果のベクトルに名前を付けるための列 | 存在する列名であること |
| ... | any | No | メソッド用の追加引数 | - |

### 入力データソース

- Rセッション内のdata.frame、tibble、またはその派生クラスのオブジェクト
- dbplyrなどのリモートデータソース

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | vector | .dataと同じサイズのベクトル |

### 出力先

- Rセッション内のオブジェクトとして返却

### 出力特性

- 戻り値は`.data`の行数と同じ長さのベクトル
- `name`引数が指定された場合、名前付きベクトルが返される
- 列の型がそのまま保持される

## 処理フロー

### 処理シーケンス

```
1. UseMethod("pull")によるメソッドディスパッチ
   └─ .dataの型に応じた適切なメソッドが呼び出される
2. tidyselect::vars_pull()で列名を解決
   └─ 正の整数、負の整数、列名のいずれも対応
3. name引数の処理
   └─ NULLなら単純な列抽出、指定があれば名前用の列も解決
4. 列の抽出
   └─ .data[[var]]で列をベクトルとして取得
5. 名前の設定（必要な場合）
   └─ set_names()で名前を設定
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[pull呼び出し]
    B --> C[UseMethodでディスパッチ]
    C --> D[vars_pullで列名解決]
    D --> E{name引数がNULL?}
    E -->|Yes| F[.data[[var]]を返却]
    E -->|No| G[vars_pullでname列解決]
    G --> H[set_namesで名前付きベクトル作成]
    H --> I[結果を返却]
    F --> J[終了]
    I --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デフォルト列選択 | varが未指定の場合、最後の列（-1）が選択される | var引数が省略された場合 |
| BR-02 | 負のインデックス | 負の整数は末尾からの位置を示す | varが負の整数の場合 |
| BR-03 | 名前付きベクトル | name引数が指定された場合、その列の値がベクトルの名前になる | name引数が非NULL |

### 計算ロジック

**列インデックスの解決（find_var関数）**:
- 正の整数n: n番目の列を選択
- 負の整数n: (列数 + n + 1)番目の列を選択
- 例: -1は最後の列、-2は最後から2番目の列

**バリデーション**:
- `|var| > 列数` または `var == 0` の場合はエラー
- `var`が数値でも長さ1でもない場合はエラー

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

該当なし（本機能はインメモリのデータフレーム操作のみ。ただしdbplyrのリモートテーブルにも対応）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 評価エラー | varが数値でない、または長さが1でない場合 | "`var` must evaluate to a single number." メッセージを表示 |
| - | 範囲エラー | varが有効な範囲外（0や列数超過）の場合 | "`var` must be a value between {-n} and {n} (excluding zero)" メッセージを表示 |
| - | 選択エラー | 存在しない列名が指定された場合 | tidyselectによるエラーメッセージを表示 |

### リトライ仕様

該当なし（インタラクティブな関数呼び出しのため）

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

該当なし（本機能はデータベーストランザクションを使用しない）

## パフォーマンス要件

- O(1)の計算量（列の抽出は直接アクセス）
- メモリ使用量は抽出される列のサイズに比例

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

- 本機能は純粋なデータ抽出操作であり、特別なセキュリティ考慮事項はない
- リモートデータソースへのアクセスは、そのデータソースの認証・認可に依存

## 備考

- `pull()`は`$`演算子と同様の動作をするが、パイプラインでの使用に適している
- ジェネリック関数として実装されており、dbplyrなどが独自のメソッドを提供可能
- 負のインデックスによるアクセスはRの標準的な慣習に従う

---

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

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

### 推奨読解順序

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

`pull()`は入力としてdata.frameを受け取り、ベクトルを返す。オプションで名前付きベクトルを生成できる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | pull.R | `R/pull.R` | 戻り値の型（ベクトル）と名前付けの仕組み |

**読解のコツ**: `pull()`の戻り値は`.data[[var]]`による列抽出結果。`name`引数指定時は`set_names()`で名前を設定する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pull.R | `R/pull.R` | `pull()`関数のジェネリック定義（36-39行目） |
| 2-2 | pull.R | `R/pull.R` | `pull.data.frame()`メソッド実装（41-49行目） |

**主要処理フロー**:
1. **36-39行目**: ジェネリック関数定義、デフォルト`var = -1`
2. **42行目**: `tidyselect::vars_pull()`で列名を解決
3. **43-46行目**: `name`がNULLなら単純に列を返却
4. **47-48行目**: `name`指定時は名前付きベクトルを生成

#### Step 3: 補助関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | pull.R | `R/pull.R` | `find_var()`関数（51-73行目） |

**主要処理フロー**:
- **52-53行目**: 列名と位置のマッピングを作成
- **55-57行目**: varが単一の数値かを検証
- **62-66行目**: 範囲チェック
- **68-70行目**: 負のインデックスの正規化

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

```
pull(.data, var, name, ...)
    │
    ├─ check_dots_used()
    │
    ├─ UseMethod("pull")
    │      │
    │      └─ pull.data.frame()
    │             │
    │             ├─ tidyselect::vars_pull() [列名解決]
    │             │
    │             ├─ enquo(name)
    │             │
    │             ├─ quo_is_null() [name引数チェック]
    │             │
    │             ├─ .data[[var]] [列抽出]
    │             │
    │             └─ set_names() [名前付け - 条件付き]
```

### データフロー図

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

.data ─────────────────┬─ vars_pull() ─────────────────── 列名(var)
                       │         │
var (列指定) ──────────┤         ├─ 列名解決
                       │         │
name (名前用列) ───────┘         │
                                 ▼
                          .data[[var]] ─────────────────── ベクトル
                                 │
                    (name指定時)  │
                                 ▼
                           set_names() ─────────────────── 名前付きベクトル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pull.R | `R/pull.R` | ソース | pull関数のメイン実装 |
| test-pull.R | `tests/testthat/test-pull.R` | テスト | pullのユニットテスト |
