# 機能設計書 30-bind_rows

## 概要

本ドキュメントは、dplyrパッケージにおける`bind_rows`関数の機能設計を定義する。`bind_rows`は、複数のデータフレームを行方向に結合（垂直結合）し、より長いデータフレームを生成する関数である。

### 本機能の処理概要

`bind_rows`関数は、任意の数のデータフレームを行方向に結合する。列は名前でマッチングされ、一方のデータフレームにのみ存在する列は、他方のデータフレームではNAで埋められる。これはSQLのUNION ALLに類似した操作であるが、列の完全な一致は要求されない。

**業務上の目的・背景**：同じ構造（または類似構造）を持つ複数のデータセットを統合したい場合に使用する。例えば、「複数の月次データを結合して年間データを作成する」「複数のソースからのデータを統合する」「分割処理の結果を再結合する」などのケースである。`bind_rows`は、`rbind`や`do.call(rbind, list_of_dfs)`よりも柔軟で、列の不一致を自動的に処理する。

**機能の利用シーン**：
- 時系列データの期間別ファイルの結合
- 複数ソースからのデータ統合
- lapply/map処理結果のデータフレームリストの結合
- 分割処理（split-apply-combine）の結果の再結合

**主要な処理内容**：
1. 入力の正規化（リストのフラット化、NULLの除去）
2. 各入力がデータフレームまたは名前付きベクトルであることの検証
3. 名前付きベクトルをデータフレームに変換
4. .id引数が指定されている場合、識別列を追加
5. vctrs::vec_rbindによる効率的な行結合
6. 出力型の復元（最初の入力の型を継承）

**関連システム・外部連携**：vctrパッケージのvec_rbind関数を使用して効率的な行結合を実行。purrrパッケージのmap_dfrの代替として使用可能。

**権限による制御**：特になし。Rの通常のオブジェクト操作権限に依存する。

## 関連画面

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

## 機能種別

データ変換 / 結合処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ... | data.frame / list | Yes | 結合するデータフレームまたはデータフレームのリスト | data.frameまたは名前付きベクトル |
| .id | character / NULL | No | 識別列の名前 | NULL（デフォルト）または文字列 |

### 入力データソース

R環境内のdata.frame、tibble、またはそれらのリスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | data.frame / tibble | 最初の入力と同じ型で、全入力の行を含むデータフレーム |
| {.id} | character | .id指定時に追加される識別列 |

### 出力先

R環境内のオブジェクトとして返却

## 処理フロー

### 処理シーケンス

```
1. 入力の取得
   └─ list2(...): 引数をリストとして取得
2. リストのフラット化
   ├─ 単一のリストが渡された場合は展開
   └─ list_flatten: ネストされたリストをフラット化
3. NULL要素の除去
   └─ discard(is.null)
4. 最初の入力の保存
   └─ 出力型の復元に使用
5. 入力の検証と変換
   ├─ 名前付きリストで非データフレームの場合はtibbleに変換
   └─ dataframe_ish: 各要素がdata.frameまたは名前付きベクトルか確認
6. .id引数の処理
   ├─ .id指定時: 名前がない要素にはインデックスを使用
   └─ .id未指定時: 名前を除去（行名の昇格を防止）
7. vec_rbindによる結合
   └─ .names_to = .id で識別列を追加
8. 出力型の復元
   ├─ 最初の入力がdata.frameの場合: dplyr_reconstruct
   └─ それ以外: as_tibble
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[list2: 引数をリスト化]
    B --> C{単一リスト?}
    C -->|Yes| D[リストを展開]
    C -->|No| E[list_flatten]
    D --> E
    E --> F[discard: NULL除去]
    F --> G{空リスト?}
    G -->|Yes| H[空tibble返却]
    G -->|No| I[最初の入力を保存]
    I --> J{名前付き非data.frame?}
    J -->|Yes| K[as_tibbleで変換]
    J -->|No| L[dataframe_ishチェック]
    K --> L
    L --> M{.id指定?}
    M -->|Yes| N[名前がない要素にインデックス付与]
    M -->|No| O[names(dots) <- NULL]
    N --> P[vec_rbind]
    O --> P
    P --> Q{最初がdata.frame?}
    Q -->|Yes| R[dplyr_reconstruct]
    Q -->|No| S[as_tibble]
    R --> T[終了]
    S --> T
    H --> T
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-30-01 | 列名マッチング | 列は名前でマッチングされる | 常に適用 |
| BR-30-02 | 欠損列NA埋め | 一方にのみ存在する列はNAで埋められる | 列不一致時 |
| BR-30-03 | 型継承 | 結果の型は最初の入力の型を継承 | 常に適用 |
| BR-30-04 | .id識別列 | .id指定時、各入力を識別する列が追加される | .id指定時 |
| BR-30-05 | 名前付きリスト | 名前付きリストの場合、tibbleに変換 | 特定条件下 |
| BR-30-06 | NULL除去 | NULL要素は自動的に除去される | 常に適用 |

### 計算ロジック

- **行結合**: vctrs::vec_rbindを使用して効率的に結合
- **型変換**: 列の型が異なる場合、vctrの共通型ルールに従って変換
- **識別列**: .id指定時、リスト名（なければインデックス）が識別列に設定される

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

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

本機能はインメモリ処理のため、データベース操作は発生しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 引数エラー | 引数がdata.frameでも名前付きベクトルでもない | 正しい形式の引数を指定 |
| - | check_string | .idが文字列でない | 文字列を指定 |

### リトライ仕様

該当なし（同期処理）

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

該当なし（インメモリ処理）

## パフォーマンス要件

- 計算量: O(n)（nは全入力の総行数）
- メモリ使用量: 結果行数分のメモリを消費

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

特になし。入力データの機密性は呼び出し側の責任で管理する。

## 備考

- `do.call(rbind, dfs)`と異なり、列の不一致を自動的に処理
- `purrr::map_dfr`の代替として使用可能
- 名前付きリスト入力の特殊処理は`map_dfr()`との互換性のため

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | bind-rows.R | `R/bind-rows.R` | bind_rowsのドキュメント（1-29行目） |

**読解のコツ**: 「Columns are matched by name, and any missing columns will be filled with NA」が重要な特徴。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | bind-rows.R | `R/bind-rows.R` | bind_rows関数本体（30-88行目） |

**主要処理フロー**:
1. **30行目**: 関数定義 `bind_rows <- function(..., .id = NULL)`
2. **31行目**: `list2(...)` - 引数をリストとして取得
3. **34-38行目**: リストのフラット化処理
4. **39行目**: `discard(dots, is.null)` - NULL除去
5. **42-46行目**: 最初の入力の保存
6. **48-51行目**: 名前付きリストの特殊処理
7. **53-61行目**: 各要素の検証とデータフレーム変換
8. **64-77行目**: .id引数の処理
9. **79行目**: `vec_rbind(!!!dots, .names_to = .id, ...)` - 行結合
10. **82-86行目**: 出力型の復元

#### Step 3: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | bind-rows.R | `R/bind-rows.R` | dataframe_ish関数（92-94行目） |

**主要処理フロー**:
- **93行目**: `is.data.frame(.x) || (vec_is(.x) && is_named(.x))` - data.frameまたは名前付きベクトルかを判定

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

```
bind_rows(..., .id = NULL)
    │
    ├─ list2(...)  # 引数をリストとして取得
    │
    ├─ list_flatten(dots, fn = is_flattenable)  # ネストをフラット化
    │
    ├─ discard(dots, is.null)  # NULL除去
    │
    ├─ is_named(dots) && !all(map_lgl(dots, dataframe_ish))
    │      └─ as_tibble(dots)  # 名前付きリストの場合
    │
    ├─ for each dot:
    │      ├─ dataframe_ish(.x)  # 検証
    │      └─ vctrs::data_frame(!!!.x)  # 変換
    │
    ├─ .id処理:
    │      ├─ have_name(dots)
    │      └─ 名前がない要素にインデックス付与
    │
    ├─ vec_rbind(!!!dots, .names_to = .id, ...)
    │
    └─ dplyr_reconstruct(out, first) または as_tibble(out)
```

### データフロー図

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

df1 ──┐
      │
df2 ──┼─▶ list2(...) ─▶ リスト化
      │         │
df3 ──┤         └─▶ list_flatten() ─▶ フラット化
      │                  │
list(df4,df5) ──┘        └─▶ discard(is.null) ─▶ NULL除去
                                   │
                                   └─▶ 検証 & 変換
                                          │
                                          └─▶ vec_rbind() ─▶ 行結合
                                                    │
                                                    ├─▶ .id列追加（指定時）
                                                    │
                                                    └─▶ 結果 (data.frame)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| bind-rows.R | `R/bind-rows.R` | ソース | bind_rows関数の定義 |
| vctrs.R | `R/vctrs.R` | ソース | vctrパッケージとの連携 |
