データ分析を劇的に改善！Pandasの`rank(method="dense")`と`factorize`で実現する「見やすい連番」作成術

## はじめに
データ分析をしていると、「もっとこの識別子が見やすければ…」「カテゴリごとに連番を振って比較したい…」と感じることはありませんか？ 私自身、Pandasのある機能を活用することで、分析作業が格段に効率化した経験があります。

それは、**`rank(method="dense")`** や **`pd.factorize`** を使って、データに **「dense（密な）連番」** を付与するというテクニックです。

「denseな連番」とは、簡単に言うと**1から始まる重複なし・抜けなしの綺麗な通し番号**のことです。元のデータが飛び飛びの数値だったり、長い文字列だったりしても、これらの機能を使えば、分析しやすいシンプルな連番に変換できます。

今回は、この「denseな連番」を特定の列（ここでは例として`インデックスキー`という名前の列を扱います）に対して作成し、さらにグループを示す情報（例：`グループ名`）と組み合わせることで、より便利な分析キーを作成する方法を2つご紹介します。

## なぜ「denseな連番」が便利なのか？

**連番を振りたい元の列**（例えば商品コード、ユーザー識別子など）の値が、以下のような場合に「denseな連番」が役立ちます。

*   **値が飛び飛びの数値や長い文字列:** 「ID: 105」と「ID: 203」、「商品コード: XYZ001」と「商品コード: ABC999」など、そのままでは比較や並び替えがしにくい。
*   **グループごとの集計・可視化:** カテゴリごとにデータを見たいとき、元の識別子が不規則だとグラフの軸が見づらかったり、集計結果の解釈が難しくなったりする。
*   **直感的な理解:** 単純な「1, 2, 3...」という連番は、誰にとっても分かりやすい。

「denseな連番」は、これらの問題を解決し、分析の効率と分かりやすさを向上させます。

## 方法1: `rank(method="dense")` を使う（元の列が数値比較可能な場合）

**連番を振りたい対象の列**（コード例では `インデックスキー` 列）が数値や日付など、大小比較が意味を持つデータの場合に有効な方法です。`rank()`メソッドに `method="dense"` を指定すると、同じ値には同じランク（番号）を振りつつ、次の異なる値には連番（ランク+1）を振ってくれます。

**コード例:**

```python
import pandas as pd

# 'インデックスキー' は連番を振りたい元の列、'グループ名' はカテゴリを示す列とする
data = {'インデックスキー': [10, 20, 10, 30, 20],
        'グループ名': ['チームA', 'チームA', 'チームB', 'チームA', 'チームB']}
df = pd.DataFrame(data)

print("--- 元データ ---")
print(df)

# 1. 'インデックスキー' 列に対して、dense rank を求める (1始まり)
#    小さい値から順に 1, 2, 3... と番号が付く
df["dense_index"] = df["インデックスキー"].rank(method="dense").astype(int)

# 2. 作成した dense_index と グループ名 を連結して新しいカラムを作成
#    文字列として連結するために .astype(str) を使用
df["連番とグループ名"] = df["dense_index"].astype(str) + "_" + df["グループ名"].astype(str)

# 結果を表示
print("\n--- rank(method=\"dense\") 適用後 ---")
print(df)
```

**実行結果例:**

```
--- 元データ ---
   インデックスキー   グループ名
0       10  チームA
1       20  チームA
2       10  チームB
3       30  チームA
4       20  チームB

--- rank(method="dense") 適用後 ---
   インデックスキー   グループ名  dense_index 連番とグループ名
0       10  チームA            1     1_チームA
1       20  チームA            2     2_チームA
2       10  チームB            1     1_チームB
3       30  チームA            3     3_チームA
4       20  チームB            2     2_チームB
```

この例では、元の `インデックスキー` 列の値 (10, 20, 30) に基づいて、`dense_index` 列に (1, 2, 3) という連番が振られています。そして、それを `グループ名` と連結して、`"1_チームA"` のような分かりやすいキーを作成しています。（新しい列名は `連番とグループ名` に変更しました）

## 方法2: `pd.factorize()` を使う（元の列が文字列やカテゴリ値にも有効）

**連番を振りたい対象の列**（コード例では `インデックスキー` 列）が文字列の場合や、大小比較に意味がない（出現順などで連番を振りたい）場合に非常に便利なのが `pd.factorize()` です。これは、列に含まれるユニークな値に対して、最初に出現したものから順に 0, 1, 2... と整数を割り当てます。

**コード例:**

```python
import pandas as pd

# 'インデックスキー' は連番を振りたい元の列、'グループ名' はカテゴリを示す列とする
data = {'インデックスキー': ["apple", "orange", "apple", "banana", "orange"],
        'グループ名': ['果物セットX', '果物セットX', '果物セットY', '果物セットX', '果物セットY']}
df = pd.DataFrame(data)

print("--- 元データ ---")
print(df)

# 1. 'インデックスキー' 列の固有の値に対して、出現順に dense な番号を割り当てる
#    pd.factorize は (整数配列, ユニーク値配列) のタプルを返すため [0] で整数配列を取得
#    0始まりなので +1 して 1始まりにする
df["dense_index"] = pd.factorize(df["インデックスキー"])[0] + 1

# 2. 作成した dense_index と グループ名 を連結して新しいカラムを作成
df["連番とグループ名"] = df["dense_index"].astype(str) + "_" + df["グループ名"].astype(str)

# 結果を表示
print("\n--- pd.factorize 適用後 ---")
print(df)
```

**実行結果例:**

```
--- 元データ ---
  インデックスキー     グループ名
0    apple  果物セットX
1   orange  果物セットX
2    apple  果物セットY
3   banana  果物セットX
4   orange  果物セットY

--- pd.factorize 適用後 ---
  インデックスキー     グループ名  dense_index 連番とグループ名
0    apple  果物セットX            1   1_果物セットX
1   orange  果物セットX            2   2_果物セットX
2    apple  果物セットY            1   1_果物セットY
3   banana  果物セットX            3   3_果物セットX
4   orange  果物セットY            2   2_果物セットY
```

こちらでは、`インデックスキー` 列の文字列 ("apple", "orange", "banana") に対して、出現順に `dense_index` として (1, 2, 3) が割り当てられています。文字列に対しても簡単に連番が振れ、それを `グループ名` と組み合わせることで、`"1_果物セットX"` のような直感的なキーが作れます。

## おわりに

*   **元の列の値の大小に基づいて連番を振りたい場合 → `rank(method="dense")`**
*   **元の列が文字列やカテゴリ値で、出現順などに基づいて連番を振りたい場合 → `pd.factorize()`**

どちらの方法でも、作成した `dense_index`（1から始まる連番）と、既存の「グループ名」（などのカテゴリを示す列）を `astype(str)` で文字列に変換し、`+ "_" +` のように連結すれば、`"1_チームA"`, `"2_果物セットX"` のような非常に見やすい**複合キー**を作成できます。

この「denseな連番」と「複合キー」を活用することで、データのグループ化、集計、可視化などが格段にやりやすくなります。もし、扱いにくい識別子やIDを持つデータで分析に手間取っているなら、ぜひこの方法を試してみてください。きっと「データ分析が非常にしやすくなった！」と感じていただけると思います！

## 参考
https://pandas.pydata.org/docs/reference/api/pandas.Series.rank.html

https://pandas.pydata.org/docs/reference/api/pandas.factorize.html#pandas.factorize