# 機能設計書 4-slice

## 概要

本ドキュメントは、dplyrパッケージの`slice`関数およびその派生関数群に関する機能設計書です。`slice`関数は、インデックス（行番号）に基づいてデータフレームの行を選択する機能を提供します。

### 本機能の処理概要

`slice`関数は、整数インデックスを使用してデータフレームの行を選択、除外、または複製するデータ操作関数です。以下のヘルパー関数も含まれます：

- `slice_head()`: 先頭から指定数の行を選択
- `slice_tail()`: 末尾から指定数の行を選択
- `slice_min()`: 指定変数の最小値を持つ行を選択
- `slice_max()`: 指定変数の最大値を持つ行を選択
- `slice_sample()`: ランダムに行を選択

**業務上の目的・背景**：データ分析において、特定の位置にある行や上位/下位N件のデータを取得することは頻繁に必要とされます。SQLのLIMIT句やROW_NUMBER()に相当する機能を提供し、ヘルパー関数により直感的なコードでよく使われる操作を実現できます。グループ化されたデータでは、各グループ内で独立して操作が適用されます。

**機能の利用シーン**：
- 先頭N件のデータを確認（head相当）
- 売上上位10社を抽出
- 各グループから代表的なサンプルを抽出
- データのランダムサンプリング

**主要な処理内容**：
1. 引数のバリデーション（`.by`と`.preserve`の同時指定チェック等）
2. グループ化情報の計算
3. インデックス式の評価
4. 各グループでのインデックス計算
5. 範囲外インデックスの除去
6. `dplyr_row_slice`による行の抽出

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

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

## 関連画面

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

## 機能種別

データ操作（行の選択）/ データ変換

## 入力仕様

### 入力パラメータ

#### slice()

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

#### slice_head() / slice_tail()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| n | integer | No | 選択する行数 | 整数、負の値で残りを選択 |
| prop | numeric | No | 選択する割合 | 0-1の数値 |
| by | tidy-select | No | グループ化に使用する列 | - |

#### slice_min() / slice_max()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| order_by | expression | Yes | ソート基準の列または式 | - |
| n / prop | - | No | 行数または割合 | - |
| with_ties | logical | No | 同順位を含めるか（デフォルト: TRUE） | - |
| na_rm | logical | No | NAを除外するか（デフォルト: FALSE） | - |

#### slice_sample()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| n / prop | - | No | 行数または割合 | - |
| weight_by | expression | No | サンプリング重み | 非負の数値ベクトル |
| replace | logical | No | 復元抽出か（デフォルト: FALSE） | - |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | .dataと同じ型 | 選択された行を含むデータフレーム |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. 引数バリデーション
   └─ .byと.preserveの同時指定チェック
   └─ n/propの整合性チェック
2. グループ化情報の計算
   └─ compute_by()でグループ情報を取得
3. slice_rows()の実行
   └─ DataMask$new()でデータマスクを作成
   └─ slice_eval()でインデックス式を評価
   └─ slice_combine()で各グループのインデックスを結合
4. dplyr_row_slice()で行を抽出
```

### フローチャート

```mermaid
flowchart TD
    A[slice開始] --> B{引数バリデーション}
    B -->|エラー| E1[エラー終了]
    B -->|OK| C[グループ化計算]
    C --> D[slice_rows]
    D --> E[DataMask作成]
    E --> F[slice_eval]
    F --> G[各グループでインデックス評価]
    G --> H[slice_combine]
    H --> I[範囲外インデックス除去]
    I --> J[dplyr_row_slice]
    J --> K[結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | インデックスの符号 | 正のインデックスは保持、負のインデックスは除外 | 混在不可 |
| BR-02 | 範囲外インデックス | 行数を超えるインデックスは無視される | 常時 |
| BR-03 | グループ内適用 | grouped_dfでは各グループ内で独立して適用 | grouped_df使用時 |
| BR-04 | n/propの優先度 | nとpropは同時指定不可、どちらか一方のみ | slice_*関数 |
| BR-05 | 同順位の扱い | with_ties=TRUEで指定より多い行が返る可能性 | slice_min/max |

### 計算ロジック

- `n`指定時: 先頭/末尾からn行を選択
- `prop`指定時: `floor(prop * グループサイズ)`行を選択
- 負の`n`/`prop`: グループサイズから引いた数を選択
- `slice_sample`の重み: `sample.int()`の`prob`引数に渡される

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | abort | .byと.preserveを同時指定 | どちらか一方のみ指定 |
| - | abort | nとpropを同時指定 | どちらか一方のみ指定 |
| - | abort | nが整数でない | 整数値を指定 |
| - | abort | 正負のインデックス混在 | どちらか一方に統一 |
| - | vctrs_error_subscript | 不正なインデックス型 | 整数を使用 |

### リトライ仕様

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

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

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

## パフォーマンス要件

- インデックス計算はグループごとに独立して実行
- 大規模データセットでも効率的に動作

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

- 入力データの検証はdplyrフレームワーク内で実施

## 備考

- リレーショナルデータベースには行順序の概念がないため、dbplyrでは使用不可
- `filter()`と`row_number()`の組み合わせでSQL互換の実装が可能

---

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

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

### 推奨読解順序

#### Step 1: slice関数の基本構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | slice.R | `R/slice.R` | slice関数とヘルパー関数の定義 |

**読解のコツ**: slice.Rには複数の関数が定義されている。基本のslice()とヘルパー関数（slice_head等）の関係を理解する。

**主要処理フロー**:
- **131-141行目**: slice関数定義
- **143-158行目**: slice.data.frame実装
- **162-182行目**: slice_head関数
- **220-274行目**: slice_min関数

#### Step 2: インデックス処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | slice.R | `R/slice.R` | slice_rows, slice_eval, slice_combine関数 |

**主要処理フロー**:
- **393-414行目**: slice_rows関数
- **424-484行目**: slice_eval関数 - インデックス式の評価
- **486-519行目**: slice_combine関数 - グループごとの結果結合

#### Step 3: サイズ計算を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | slice.R | `R/slice.R` | get_slice_size関数 |

**主要処理フロー**:
- **584-615行目**: get_slice_size関数 - n/propからサイズ計算
- **617-625行目**: clamp関数 - 範囲内に収める

#### Step 4: ランキング処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | slice.R | `R/slice.R` | slice_rank_idx関数 |

**主要処理フロー**:
- **635-666行目**: slice_rank_idx関数 - min/maxのランキングベース選択

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

```
slice(.data, ..., .by, .preserve)
    │
    └─ UseMethod("slice")
           │
           └─ slice.data.frame(.data, ..., .by, .preserve)
                  │
                  ├─ compute_by(.by, .data)
                  │
                  ├─ slice_rows(.data, dots, by)
                  │      │
                  │      ├─ DataMask$new(data, by, "slice")
                  │      ├─ slice_eval(mask, dots)
                  │      │      └─ vec_as_subscript() - インデックス変換
                  │      └─ slice_combine(chunks, dots, mask)
                  │             └─ num_as_location() - 範囲チェック
                  │
                  └─ dplyr_row_slice(.data, loc, preserve)

slice_head/.../slice_sample
    │
    └─ slice(.data, idx(n()), .by)  ← 内部でsliceを呼び出し
```

### データフロー図

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

.data (data.frame)  ───▶ グループ化 ───▶ インデックス評価 ───▶ 結合
      │                       │                  │              │
      │                       ▼                  ▼              ▼
      │                  グループ情報      各グループのloc    全体のloc
      │                       │                  │              │
      └───────────────────────┴──────────────────┴──────────────┘
                                                                │
                                                                ▼
                                                      dplyr_row_slice
                                                                │
                                                                ▼
                                                        結果data.frame
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| slice.R | `R/slice.R` | ソース | slice関数群の実装 |
| 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関数の実装 |
