# 機能設計書 3-arrange

## 概要

本ドキュメントは、dplyrパッケージの`arrange`関数に関する機能設計書です。`arrange`関数は、列の値に基づいてデータフレームの行を並び替える機能を提供します。

### 本機能の処理概要

`arrange`関数は、指定された列の値に基づいてデータフレームの行をソートするデータ操作関数です。複数の列を指定した場合は、最初の列で並び替えた後、同じ値を持つ行内で次の列によるソートが行われます。`desc()`関数を使用することで降順ソートを指定できます。

**業務上の目的・背景**：データ分析において、データを特定の順序で並び替えることは頻繁に必要とされる操作です。売上高順、日付順、アルファベット順などでデータを整理することで、データの傾向把握や上位/下位データの抽出が容易になります。SQLのORDER BY句に相当する機能を提供し、ベースRの`order`関数よりも直感的で可読性の高いコードを実現します。

**機能の利用シーン**：
- 売上データを金額の降順で並び替え
- 日付順でのログデータの整理
- 複数条件でのソート（例：部門→売上額）
- カテゴリ別、サブカテゴリ別の階層的ソート

**主要な処理内容**：
1. 引数の解析とquosure変換
2. グループ化データの場合、`.by_group = TRUE`でグループ変数を先頭に追加
3. `desc()`呼び出しの検出と方向（asc/desc）の決定
4. 各ソートキーの評価
5. `vec_order_radix`または`order`を使用したソート位置の計算
6. `dplyr_row_slice`による行の並び替え

**関連システム・外部連携**：
- vctrs: `vec_order_radix`によるソート
- stringi: ロケール指定時の文字列ソート
- rlang: quosureとデータマスキング機能

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

## 関連画面

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

## 機能種別

データ操作（行の並び替え）/ データ変換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| .data | data.frame | Yes | 並び替え対象のデータフレーム | data.frameまたはその派生クラス |
| ... | expressions | No | ソートキーとなる列または式 | 評価可能な式であること |
| .by_group | logical | No | グループ変数で先にソートするか（デフォルト: FALSE） | grouped_dfの場合のみ有効 |
| .locale | character | No | 文字列ソートに使用するロケール | NULL、"C"、またはstringiのロケール |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | .dataと同じ型 | 並び替えられたデータフレーム |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. 引数の解析
   └─ enquos(...)でソートキーをquosureに変換
2. グループ変数の追加（オプション）
   └─ .by_group = TRUEの場合、グループ変数をソートキーの先頭に追加
3. arrange_rows()の実行
   └─ desc()呼び出しの検出と方向決定
   └─ 各ソートキーの評価（mutateを使用）
   └─ ロケールの処理
4. ソート位置の計算
   └─ vec_order_radix()でソートインデックスを計算
   └─ または、レガシーモードでorder()を使用
5. dplyr_row_slice()で行を並び替え
```

### フローチャート

```mermaid
flowchart TD
    A[arrange開始] --> B[enquos処理]
    B --> C{.by_group?}
    C -->|TRUE| D[グループ変数を先頭に追加]
    C -->|FALSE| E[arrange_rows]
    D --> E
    E --> F[desc検出と方向決定]
    F --> G[各ソートキーを評価]
    G --> H{.locale指定?}
    H -->|NULL/C| I[デフォルトソート]
    H -->|ロケール指定| J[stringiでソートキー生成]
    I --> K[vec_order_radix]
    J --> K
    K --> L[dplyr_row_slice]
    L --> M[結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | NA値の扱い | NAは常に末尾にソートされる（desc()でも同様） | 常時 |
| BR-02 | 複数キーのソート | 最初のキーでソート後、同値内で次のキーでソート | 複数キー指定時 |
| BR-03 | グループの無視 | arrange()は基本的にグループを無視してソート | grouped_df使用時 |
| BR-04 | グループ優先ソート | .by_group = TRUEでグループ変数が最優先 | .by_group指定時 |
| BR-05 | 列の不変 | ソートしても列は変更されない | 常時 |

### 計算ロジック

- 昇順（デフォルト）: 小さい値から大きい値へ
- 降順（desc()指定）: 大きい値から小さい値へ
- NA値: 方向に関係なく常に末尾
- 文字列ソート: デフォルトはCロケール（ASCII順）

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | abort | desc()が1引数以外で呼び出された場合 | desc()は1引数のみ |
| - | abort | .localeが無効な文字列の場合 | stringi::stri_locale_list()から選択 |
| - | abort | stringiがインストールされていない場合（ロケール指定時） | stringi >=1.5.3をインストール |

### リトライ仕様

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

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

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

## パフォーマンス要件

- vctrsの`vec_order_radix`を使用し、効率的なradixソートを実現
- Cロケールは最も高速（stringi不要）
- カスタムロケールはstringiのソートキー生成により若干オーバーヘッドあり

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

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

## 備考

- `dplyr.legacy_locale`グローバルオプションでシステムロケールを使用可能（非推奨）
- desc()関数はR/desc.Rで定義されている
- grouped_dfに対するarrange()はグループを再計算しない

---

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

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

### 推奨読解順序

#### Step 1: arrangeの基本構造を理解する

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

**読解のコツ**: arrange関数は比較的シンプルな構造で、arrange_rows関数に処理を委譲している。

**主要処理フロー**:
- **82-84行目**: arrange関数定義（ジェネリック関数）
- **88-97行目**: arrange.data.frame実装

#### Step 2: ソート処理の詳細を理解する

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

**主要処理フロー**:
- **101-187行目**: arrange_rows関数
- **110-129行目**: desc()呼び出しの検出と方向決定
- **137-155行目**: 各ソートキーの評価（mutateを使用）
- **181-186行目**: vec_order_radixによるソート

#### Step 3: desc関数を理解する

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

**読解のコツ**: desc()は実際の降順ソートを行うのではなく、arrange_rowsで方向フラグとして使用されるマーカー。

#### Step 4: ロケール処理を理解する

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

**主要処理フロー**:
- **189-225行目**: locale_to_chr_proxy_collate関数
- **227-231行目**: sort_key_generator - stringiでソートキー生成

#### Step 5: レガシーモードを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | arrange.R | `R/arrange.R` | dplyr_order_legacy関数 |

**主要処理フロー**:
- **235-245行目**: dplyr_order_legacy - 旧式のorder()ベースソート
- **247-294行目**: dplyr_proxy_order_legacy - プロキシ生成

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

```
arrange(.data, ..., .by_group)
    │
    └─ UseMethod("arrange")
           │
           └─ arrange.data.frame(.data, ..., .by_group, .locale)
                  │
                  ├─ enquos(...)
                  ├─ (.by_group) ? quos(!!!groups(.data)) + dots
                  │
                  ├─ arrange_rows(data, dots, locale)
                  │      │
                  │      ├─ desc()検出 → directions[]
                  │      ├─ desc()除去 → dots[]
                  │      │
                  │      ├─ for each dot:
                  │      │      └─ mutate(data, "{name}" := !!dot)
                  │      │
                  │      ├─ locale_to_chr_proxy_collate(locale)
                  │      │      └─ (ロケール指定時) sort_key_generator(locale)
                  │      │
                  │      └─ vec_order_radix(data, directions, na_values, chr_proxy_collate)
                  │
                  └─ dplyr_row_slice(.data, loc)
```

### データフロー図

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

.data (data.frame)  ───▶ ソートキー抽出 ───▶ 方向決定 ───▶ キー評価
      │                       │                  │              │
      │                       ▼                  ▼              ▼
      │                  desc()検出          asc/desc      各キーの値
      │                       │                  │              │
      └───────────────────────┴──────────────────┴──────────────┘
                                                                │
                                                                ▼
                                                      vec_order_radix
                                                                │
                                                                ▼
                                                          loc (integer)
                                                                │
                                                                ▼
                                                      dplyr_row_slice
                                                                │
                                                                ▼
                                                        結果data.frame
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| arrange.R | `R/arrange.R` | ソース | arrange関数の実装 |
| desc.R | `R/desc.R` | ソース | desc関数の実装 |
| generics.R | `R/generics.R` | ソース | dplyr_row_slice等の汎用関数 |
| locale.R | `R/locale.R` | ソース | ロケール関連ヘルパー |
| grouped-df.R | `R/grouped-df.R` | ソース | grouped_df関連の定義 |
