Python | データ処理:pandas のインデックス管理

Python
スポンサーリンク
  1. 概要(インデックス管理は「行ラベルを設計して、選択・結合・時系列操作を安定化」する)
  2. 基本操作(作成・設定・リセット・名前・ソート)
    1. デフォルトのインデックスと設定・リセット
    2. インデックス名の管理(rename_axis)
    3. 並べ替え(sort_index)と行アクセスの安定化
  3. インデックスの種類と特性(単一、マルチ、日時)
    1. 単一インデックス(主キー設計の基本)
    2. マルチインデックス(複合キーで階層管理)
    3. DatetimeIndex(時系列の“文字列スライス”が効く)
  4. 選択の型(locとiloc、スライス、部分一致)
    1. loc(ラベル選択)と列同時指定
    2. iloc(位置選択)で安全にスライス
    3. マルチインデックスのスライス・部分キー
  5. 再配置と整列(reindex、欠損の扱い、連結前の下準備)
    1. reindexで「欲しい軸」に揃える
    2. 時系列の等間隔化・補間
  6. インデックスと結合・グループ化(join/merge、groupby、重複)
    1. joinは“インデックスで横結合”
    2. mergeは“列で結合”(インデックスを戻す)
    3. groupbyは“インデックスでも”動く
    4. 重複インデックスは増殖に注意
  7. 重要ポイントの深掘り(型の統一・一意性・日時の昇順・不変性)
    1. dtypeの統一が結合と選択の前提
    2. is_uniqueで“主キーらしさ”を保証
    3. DatetimeIndexは昇順ソートが必須
    4. Indexは不変(immutable)を前提に扱う
  8. 実践例(時系列ダッシュボード整備、複合キーの補完、行選択の安全化)
    1. 月次に揃えてから突き合わせ(時系列の整形→join)
    2. マルチインデックスで目標突き合わせ
    3. locで意味ベースの抽出を型にする
  9. まとめ(「set_indexで主キー化」「reset_indexで柔軟化」「sort/reindexで軸を整える」)

概要(インデックス管理は「行ラベルを設計して、選択・結合・時系列操作を安定化」する)

pandasのインデックスは“行のラベル”です。単なる番号ではなく、選択(loc)、結合(join/merge)、並べ替え(sort_index)、再配置(reindex)、時系列の文字列スライスなどを支える土台。初心者は「インデックスの種類(単一・マルチ・日時)」「set_index/reset_indexの使い分け」「is_unique(一意性)と型の統一」「reindexとsort_index」「loc/ilocの正しい使い分け」を型として押さえると、実務で迷いません。


基本操作(作成・設定・リセット・名前・ソート)

デフォルトのインデックスと設定・リセット

import pandas as pd

df = pd.DataFrame({
    "id": [101, 102, 103],
    "name": ["Alice", "Bob", "Charlie"],
    "score": [85, 90, 78]
})

df_id = df.set_index("id")         # 列をインデックスへ
df_back = df_id.reset_index()      # インデックスを列へ戻す
Python

set_indexは「主キー」を行ラベルに昇格させ、joinやloc選択を短く安全にします。reset_indexは逆に“表形式”へ戻すための定番です。

インデックス名の管理(rename_axis)

df_id = df.set_index("id")
df_id = df_id.rename_axis("student_id")   # 行側のラベル名
Python

index.nameはレポート・保存時の可読性に効きます。列の名前とは別軸のラベルです。

並べ替え(sort_index)と行アクセスの安定化

df_sorted = df_id.sort_index()  # 行ラベルで昇順
Python

時系列スライスや二分探索ベースの効率化に役立ちます。日時系は必ず昇順へ整えます。


インデックスの種類と特性(単一、マルチ、日時)

単一インデックス(主キー設計の基本)

単一のキー(idなど)をインデックスにすると、locで一発選択、joinで短く結合できます。重複があると「多対多」になり得るため、is_uniqueで確認します。

print(df_id.index.is_unique)  # 一意であれば True
Python

マルチインデックス(複合キーで階層管理)

sales = pd.DataFrame({
    "store": ["A","A","B","B"],
    "month": ["Jan","Feb","Jan","Feb"],
    "sales": [100,120,90,110]
}).set_index(["store","month"])

print(sales.loc[("A","Jan")])   # 組で選択
print(sales.sort_index())       # 階層ごとに並べ替え
Python

複数列をキー化し、階層的な選択・集計が自然になります。階層順の設計(どれを外側に置くか)が重要です。

DatetimeIndex(時系列の“文字列スライス”が効く)

ts = pd.DataFrame({
    "date": pd.date_range("2025-01-01", periods=10, freq="D"),
    "val": range(10)
}).set_index("date").sort_index()

print(ts.loc["2025-01"])             # 月指定で一括選択
print(ts.loc["2025-01-03":"2025-01-06"])  # 端点を含む範囲
Python

DateTimeIndex+昇順で、月/日/時の文字列スライスが直感的に使えます。to_datetime→sort_indexがセットです。


選択の型(locとiloc、スライス、部分一致)

loc(ラベル選択)と列同時指定

row = df_id.loc[102]                         # 行ラベルで選ぶ
subset = df_id.loc[[101,103], ["name","score"]]  # 行と列を同時に
Python

locは“ラベル”で選びます。インデックスを主キー化すれば、意図通りに“意味で”選択できます。

iloc(位置選択)で安全にスライス

first_two = df_id.iloc[:2]     # 先頭2行(0始まり)
second_col = df_id.iloc[:, 1]  # 列の位置で選ぶ
Python

列名変更やインデックス変更の影響を受けず、位置で扱いたいときに使います。

マルチインデックスのスライス・部分キー

# 外側キーだけでスライス(storeごと)
print(sales.loc["A"])
# 部分スライスは slice を使う
print(sales.loc[("A", slice("Jan","Feb")), :])
Python

階層に沿った選択が自然に書けます。部分キーでの選択は“外側→内側”の順を守ります。


再配置と整列(reindex、欠損の扱い、連結前の下準備)

reindexで「欲しい軸」に揃える

target_idx = [101, 102, 104]  # 104は存在しない
aligned = df_id.reindex(target_idx)
Python

存在しないラベルはNaNになります。fill_valueやmethodで埋め方を制御できます。

filled = df_id.reindex(target_idx, fill_value=0)
Python

時系列の等間隔化・補間

daily = ts.reindex(pd.date_range(ts.index.min(), ts.index.max(), freq="D"))
filled = daily.ffill()  # 欠損を直前値で補間
Python

結合前に“同じ軸”へ揃えることで、ズレない比較・joinが可能になります。


インデックスと結合・グループ化(join/merge、groupby、重複)

joinは“インデックスで横結合”

info = pd.DataFrame({"score": [88, 92]}, index=[101, 103])
out = df_id.join(info, how="left")   # id基準で結合
Python

キーをインデックスにしておくと、joinが最短で安全に書けます。衝突列はlsuffix/rsuffixで回避します。

mergeは“列で結合”(インデックスを戻す)

out2 = df_id.reset_index().merge(info.reset_index(), on="id", how="left")
Python

列基準の柔軟な結合が必要ならreset_index→mergeの流れが定番です。

groupbyは“インデックスでも”動く

mean_by_id = df_id.groupby(level=0)["score"].mean()
Python

levelで階層を指定できます。マルチインデックスではlevel番号や名前でターゲットを明示します。

重複インデックスは増殖に注意

インデックスが重複しているとjoin・groupbyで行が増えます(多対多)。意図がない場合はreset_index→drop_duplicatesでユニーク化してから設計します。

df_unique = df_id.reset_index().drop_duplicates(subset=["id"]).set_index("id")
Python

重要ポイントの深掘り(型の統一・一意性・日時の昇順・不変性)

dtypeの統一が結合と選択の前提

idが片方int、片方strだと一致しません。astypeで揃えてからset_index/mergeへ。

df["id"] = df["id"].astype("int64")
Python

is_uniqueで“主キーらしさ”を保証

assert df_id.index.is_unique, "主キーが重複しています"
Python

早めのチェックが事故を防ぎます。特にjoin前に必ず確認します。

DatetimeIndexは昇順ソートが必須

文字列スライス(”2025-01″)や範囲選択は昇順で意味を持ちます。to_datetime→sort_indexの型を徹底します。

Indexは不変(immutable)を前提に扱う

df.indexは基本的に“値を直接書き換えない”設計です。変更はrename_axis、set_index、reset_index、reindexで“宣言的に”行います。


実践例(時系列ダッシュボード整備、複合キーの補完、行選択の安全化)

月次に揃えてから突き合わせ(時系列の整形→join)

sales = pd.Series([100,120,80], index=pd.to_datetime(["2025-01-01","2025-01-03","2025-01-15"]))
users = pd.Series([50,60,55],   index=pd.to_datetime(["2025-01-02","2025-01-03","2025-01-15"]))

sM = sales.resample("D").sum().resample("M").sum()
uM = users.resample("D").sum().resample("M").sum()

out = sM.to_frame("sales").join(uM.to_frame("users"), how="outer")
Python

粒度を合わせてからjoinすると、ズレないダッシュボードが作れます。

マルチインデックスで目標突き合わせ

facts = pd.DataFrame({
    "store":["A","A","B","B"],
    "month":["Jan","Feb","Jan","Feb"],
    "sales":[100,120,90,110]
}).set_index(["store","month"])

target = pd.DataFrame({
    "store":["A","B"],
    "month":["Jan","Jan"],
    "goal":[110,95]
}).set_index(["store","month"])

out = facts.join(target, how="left")
Python

複合キーをインデックスへ。locで特定店舗・月だけを切り出すのも簡単になります。

locで意味ベースの抽出を型にする

# id=102の人のscoreだけを取る(意味で選ぶ)
score_102 = df_id.loc[102, "score"]
Python

主キー設計+locで「意図」がそのままコードに現れます。


まとめ(「set_indexで主キー化」「reset_indexで柔軟化」「sort/reindexで軸を整える」)

インデックス管理は、行ラベルを設計して操作を“意味で”安定させる技術です。主キーはset_indexで昇格、テーブル結合や加工が複雑ならreset_indexで列へ戻す。時系列はto_datetime→sort_index→reindex(等間隔)を型にし、join/merge前にdtypeとis_uniqueを確認する。loc/ilocを使い分け、マルチインデックスで複合キーを自然に扱う。これを徹底すれば、初心者でも“崩れない、迷わない、短く書ける”pandas運用が実現できます。

タイトルとURLをコピーしました