# 機能設計書 54-dense_rank

## 概要

本ドキュメントは、dplyrパッケージにおける`dense_rank()`関数の機能設計を定義する。`dense_rank()`は同順位に同じ値を付与し、次の順位にギャップを生じさせないランキング関数である。

### 本機能の処理概要

**業務上の目的・背景**：ランキング処理において、同順位の項目があっても連続した番号を維持したい場合がある。例えば、売上高ランキングで1位が3社ある場合、次の企業を2位として扱いたいケースである。`dense_rank()`は、このような「密なランキング」（ギャップなしのランキング）を実現するために設計された。

**機能の利用シーン**：連続したグループ番号が必要な場合、タイを考慮しつつも順位の連続性を保ちたい場合、ユニークな値の数に基づいたグループ化を行いたい場合に利用される。

**主要な処理内容**：
1. 入力ベクトルの値を昇順で評価し、各値にランクを付与する
2. 同じ値（タイ）がある場合、すべてに同じランク値を付与する
3. 次の異なる値のランクは、直前のランク+1となる（ギャップなし）
4. 欠損値（NA）はランクNAとして扱われる

**関連システム・外部連携**：vctrsパッケージの`vec_rank()`関数を`ties = "dense"`オプションで使用する。

**権限による制御**：本関数に権限による実行制御は存在しない。

## 関連画面

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

## 機能種別

計算処理 / ランキング関数

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| x | vector / data.frame | Yes | ランク付けする対象ベクトルまたはデータフレーム | 順序付け可能な型であること |

### 入力データソース

Rのベクトルまたはデータフレーム。`mutate()`や`filter()`内で使用される場合は、現在処理中のグループのデータが対象となる。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | integer | 整数のランクベクトル。同じ値には同じランクが付与され、ギャップなく連続する |

### 出力先

関数の戻り値として返却される。通常は`mutate()`や`filter()`の結果としてデータフレームの列に格納される。

## 処理フロー

### 処理シーケンス

```
1. 入力ベクトル x を受け取る
2. vec_rank(x, ties = "dense", incomplete = "na") を呼び出し
   └─ 値を昇順でソート
   └─ 同じ値には同じランクを付与
   └─ 異なる値には直前のランク+1を付与
3. 整数ベクトルとして結果を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始: dense_rank] --> B[vec_rank を呼び出し]
    B --> C["ties='dense', incomplete='na'"]
    C --> D[同じ値に同じランクを付与]
    D --> E[次の値は直前ランク+1]
    E --> F[ギャップなしのランクベクトル生成]
    F --> G[整数ベクトルを返却]
    G --> H[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-54-01 | 同順位処理 | 同じ値にはすべて同じランクを付与 | タイ存在時 |
| BR-54-02 | ギャップなし | 次の異なる値は直前ランク+1（連続番号） | 常に適用 |
| BR-54-03 | NA処理 | 欠損値にはNAランクを付与 | NA存在時 |
| BR-54-04 | 昇順ランク | 最小値にランク1を付与 | 常に適用 |
| BR-54-05 | 最大ランク | 最大ランク値 = ユニークな値の数 | 常に適用 |

### 計算ロジック

- `dense_rank(x)`: 同じ値には同じランク、次の値は+1
- 例: `c(10, 20, 20, 30)` → `c(1, 2, 2, 3)`
  - 10は1位
  - 20が2つあり、どちらも2位
  - 30は3位（ギャップなし）
- `min_rank()`との違い: min_rankでは上記が`c(1, 2, 2, 4)`になる

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

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

本関数はインメモリのベクトル操作のみを行い、データベース操作は行わない。

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 型エラー | 順序付けできない型の入力 | 順序付け可能な型を使用する |

### リトライ仕様

リトライは不要（同期的なインメモリ処理）。

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

トランザクション管理は不要（ステートレスな関数型処理）。

## パフォーマンス要件

- 計算量: O(n log n)（ソートベースのランキング）
- メモリ使用量: O(n)（出力ベクトル用）
- vctrsパッケージの最適化されたランキングアルゴリズムを使用

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

特別なセキュリティ考慮事項はない。

## 備考

- SQLの`DENSE_RANK()`ウィンドウ関数に相当
- `min_rank()`と似ているが、ギャップが生じない点が異なる
- 最大ランク値はユニークな値の数に等しい

---

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

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

### 推奨読解順序

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

dense_rank関数は、vctrsパッケージのvec_rank関数に依存している。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | rank.R | `R/rank.R` | ランキング関数群の定義とドキュメント |

**読解のコツ**: ドキュメント内の例 `c(10, 20, 20, 30)` → `c(1, 2, 2, 3)` でdense_rankの特徴（ギャップなし）を理解できる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | rank.R | `R/rank.R` | `dense_rank()`関数の定義（75-77行目） |

**主要処理フロー**:
1. **75行目**: `dense_rank(x)`関数のシグネチャ
2. **76行目**: `vec_rank(x, ties = "dense", incomplete = "na")` を呼び出し
3. タイには同じランク値、次の値は+1（ties = "dense"）

#### Step 3: 他のランキング関数との比較

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | rank.R | `R/rank.R` | 15-17行目の説明でdense_rankの特徴を理解 |

**主要処理フロー**:
- 15-17行目: `dense_rank()`は`min_rank()`と似ているがギャップがない
- 例: `c(10, 20, 20, 30)` → `c(1, 2, 2, 3)`

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

```
dense_rank(x)
    │
    └─ vec_rank(x, ties = "dense", incomplete = "na")
           │
           └─ [vctrsパッケージ内部処理]
                  ├─ ソート処理
                  ├─ タイ検出
                  └─ 連続ランク割り当て
```

### データフロー図

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

x = [10,20,20,30] ───▶  dense_rank(x)              ───▶  [1, 2, 2, 3]
                         │                                (ギャップなし)
                         └─▶ vec_rank(ties="dense")
                               ├─ 10 → ランク1
                               ├─ 20 → ランク2（2つとも）
                               └─ 30 → ランク3（連続）

比較: min_rank(x)の場合                              [1, 2, 2, 4]
                                                      (ギャップあり)
```

### 関連ファイル一覧

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