# 機能設計書 15-rowwise

## 概要

本ドキュメントは、dplyrパッケージの`rowwise()`関数に関する機能設計書である。この関数は、データフレームを行単位でグループ化し、各行に対して個別に計算を適用できるようにする機能を提供する。

### 本機能の処理概要

`rowwise()`関数は、データフレームを行ごとにグループ化した`rowwise_df`クラスのオブジェクトに変換する。これにより、`mutate()`や`summarise()`などの操作が各行に対して個別に適用される。ベクトル化されていない関数を行ごとに適用する場合に特に有用である。

**業務上の目的・背景**：Rの多くの関数はベクトル化されており、データフレームの列全体に対して一度に操作を行う。しかし、行ごとに異なる計算を行いたい場合（例：各行の複数列の平均値、行ごとに異なるパラメータでの計算）には、ベクトル化された方法が存在しないことがある。`rowwise()`は、このような行単位の計算を直感的に記述するための機能を提供する。

**機能の利用シーン**：
- 各行の複数列の値を使った計算（例：行ごとの平均、最小値、最大値）
- 行ごとに異なるパラメータを使用した関数呼び出し
- シミュレーションで各行が異なる設定を持つ場合
- リスト列の要素に対して行ごとに操作を行う場合
- ベクトル化されていない関数を各行に適用する場合

**主要な処理内容**：
1. `UseMethod()`によるメソッドディスパッチ
2. データフレームの型に応じた処理
   - `data.frame`: 指定された変数でrowwise_dfを構築
   - `grouped_df`: グループ変数をそのまま保持変数として使用（追加引数不可）
3. `rowwise_df()`で行ごとのグループ情報を持つオブジェクトを生成
4. グループデータには各行のインデックスが`.rows`列として格納

**関連システム・外部連携**：`summarise()`実行後は`grouped_df`が返される。`ungroup()`または`as_tibble()`でrowwise状態を解除。`c_across()`と組み合わせて複数列の値を効率的に取得。

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

## 関連画面

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

## 機能種別

データ変換処理（グループ操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| data | data.frame | Yes | 操作対象のデータフレーム | data.frameまたはその派生クラスであること |
| ... | tidy-select | No | summarise()時に保持する変数 | 存在する変数であること |

### 入力データソース

- Rセッション内のdata.frame、tibble、grouped_df、またはその派生クラスのオブジェクト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | rowwise_df | 行単位でグループ化されたデータフレーム |

### 出力先

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

### 出力特性

- 戻り値は`rowwise_df`クラス（`grouped_df`ではない）
- 各行が1つのグループとなる
- データの行と列は変更されない
- `summarise()`実行後は`grouped_df`に変換される

## 処理フロー

### 処理シーケンス

```
1. UseMethod("rowwise")によるメソッドディスパッチ
   └─ dataの型に応じた適切なメソッドが呼び出される
2. 型別の処理
   ├─ data.frame:
   │    ├─ tidyselect::eval_select()で保持変数を特定
   │    └─ rowwise_df()でオブジェクト構築
   └─ grouped_df:
        ├─ 追加引数がある場合はエラー
        └─ グループ変数を保持変数としてrowwise_df()構築
3. rowwise_df()でグループデータを生成
   └─ .rowsに各行のインデックスを設定
4. new_rowwise_df()でオブジェクトを作成
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[rowwise呼び出し]
    B --> C[UseMethodでディスパッチ]
    C --> D{dataの型は?}
    D -->|data.frame| E[eval_selectで変数選択]
    D -->|grouped_df| F{...引数あり?}
    E --> G[rowwise_df構築]
    F -->|Yes| H[エラー: 再グループ不可]
    F -->|No| I[グループ変数を取得]
    I --> J[rowwise_df構築]
    G --> K[new_rowwise_df作成]
    J --> K
    K --> L[結果を返却]
    L --> M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 行単位グループ | 各行が独立したグループとして扱われる | 常に適用 |
| BR-02 | 保持変数 | 指定した変数はsummarise()後も保持される | ...に変数が指定された場合 |
| BR-03 | grouped_df変換 | grouped_dfに対しては追加引数を指定できない | grouped_dfで...が指定された場合 |
| BR-04 | リスト列の特別扱い | rowwise_dfではリスト列に対して[[]]でアクセス（[]ではなく） | リスト列操作時 |

### 計算ロジック

**グループデータの構築**:
```
group_data = tibble(指定された保持変数)
group_data$.rows = list(1L, 2L, 3L, ..., nrow(data)) # 各行のインデックス
```

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

該当なし（本機能はインメモリのデータフレーム操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 再グループエラー | grouped_dfで追加引数が指定された場合 | "Can't re-group when creating rowwise data. Either first `ungroup()` or call `rowwise()` without arguments." |

### リトライ仕様

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

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

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

## パフォーマンス要件

- グループ数が行数と等しくなるため、大規模データでは注意が必要
- 可能であればベクトル化された操作（`pmin()`, `pmax()`など）を使用する方が高速
- O(n)のメモリ使用量（nは行数）- 各行のインデックスを保持

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

- 本機能は純粋なデータ変換操作であり、特別なセキュリティ考慮事項はない

## 備考

- `rowwise()`は`grouped_df`に似ているが、別のクラス（`rowwise_df`）
- パフォーマンスが重要な場合は、ベクトル化された代替手段（`pmin()`, `pmax()`, `rowSums()`など）を検討
- `c_across()`と組み合わせて、選択した複数列の値を簡単に取得可能
- `nest_by()`は`rowwise()`と組み合わせたネストデータの作成に便利

---

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

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

### 推奨読解順序

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

`rowwise()`は`rowwise_df`クラスのオブジェクトを生成する。これは`tbl_df`を継承し、グループ情報を属性として保持する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | rowwise.R | `R/rowwise.R` | rowwise_dfクラスの構造（96-118行目） |

**読解のコツ**: `rowwise_df`は`groups`属性に各行のインデックスを`.rows`列として保持。各行が独立したグループとなる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | rowwise.R | `R/rowwise.R` | `rowwise()`関数のジェネリック定義（61-63行目） |
| 2-2 | rowwise.R | `R/rowwise.R` | `rowwise.data.frame()`（66-69行目） |
| 2-3 | rowwise.R | `R/rowwise.R` | `rowwise.grouped_df()`（72-81行目） |

**主要処理フロー**:
1. **61-63行目**: `UseMethod("rowwise")`によるジェネリック定義
2. **67行目**: `tidyselect::eval_select()`で保持変数を選択
3. **68行目**: `rowwise_df()`でオブジェクト構築

#### Step 3: コンストラクタを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | rowwise.R | `R/rowwise.R` | `rowwise_df()`関数（85-88行目） |
| 3-2 | rowwise.R | `R/rowwise.R` | `new_rowwise_df()`関数（96-118行目） |

**主要処理フロー（rowwise_df）**:
- **86行目**: 保持変数のデータを抽出
- **87行目**: `new_rowwise_df()`を呼び出し

**主要処理フロー（new_rowwise_df）**:
- **99-108行目**: グループデータの構築（`.rows`なし）
- **109行目**: `.rows`列の追加（各行が1要素のリスト）
- **111-117行目**: `new_tibble()`でオブジェクト作成

#### Step 4: メソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | rowwise.R | `R/rowwise.R` | `tbl_sum.rowwise_df()`（136-141行目） |
| 4-2 | rowwise.R | `R/rowwise.R` | `as_tibble.rowwise_df()`（144-146行目） |
| 4-3 | rowwise.R | `R/rowwise.R` | `[.rowwise_df`（149-158行目） |

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

```
rowwise(data, ...)
    │
    ├─ UseMethod("rowwise")
    │      │
    │      ├─ rowwise.data.frame()
    │      │      │
    │      │      ├─ tidyselect::eval_select() [変数選択]
    │      │      │
    │      │      └─ rowwise_df()
    │      │             │
    │      │             ├─ as_tibble()
    │      │             │
    │      │             └─ new_rowwise_df()
    │      │                    │
    │      │                    ├─ new_tibble() [グループデータ]
    │      │                    │
    │      │                    └─ new_list_of() [.rows生成]
    │      │
    │      └─ rowwise.grouped_df()
    │             │
    │             ├─ group_vars() [既存グループ取得]
    │             │
    │             └─ rowwise_df()
```

### データフロー図

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

data.frame ─────────┬─ rowwise.data.frame() ──────── rowwise_df
                    │         │
... (保持変数) ─────┤         ├─ eval_select()
                    │         │
                    │         └─ rowwise_df()
                    │
grouped_df ─────────┴─ rowwise.grouped_df() ──────── rowwise_df
                              │
                              ├─ group_vars()
                              │
                              └─ rowwise_df()

                    [rowwise_df 構造]

                    data: 元のデータ
                    groups属性:
                      ├─ 保持変数の列
                      └─ .rows: list(1L, 2L, 3L, ...)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| rowwise.R | `R/rowwise.R` | ソース | rowwise関数とrowwise_dfクラスの実装 |
| test-rowwise.R | `tests/testthat/test-rowwise.R` | テスト | rowwiseのユニットテスト |
| across.R | `R/across.R` | ソース | c_across関数（rowwiseと連携） |
