- 概要(インデックス管理は「行ラベルを設計して、選択・結合・時系列操作を安定化」する)
- 基本操作(作成・設定・リセット・名前・ソート)
- インデックスの種類と特性(単一、マルチ、日時)
- 選択の型(locとiloc、スライス、部分一致)
- 再配置と整列(reindex、欠損の扱い、連結前の下準備)
- インデックスと結合・グループ化(join/merge、groupby、重複)
- 重要ポイントの深掘り(型の統一・一意性・日時の昇順・不変性)
- 実践例(時系列ダッシュボード整備、複合キーの補完、行選択の安全化)
- まとめ(「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() # インデックスを列へ戻す
Pythonset_indexは「主キー」を行ラベルに昇格させ、joinやloc選択を短く安全にします。reset_indexは逆に“表形式”へ戻すための定番です。
インデックス名の管理(rename_axis)
df_id = df.set_index("id")
df_id = df_id.rename_axis("student_id") # 行側のラベル名
Pythonindex.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"]) # 端点を含む範囲
PythonDateTimeIndex+昇順で、月/日/時の文字列スライスが直感的に使えます。to_datetime→sort_indexがセットです。
選択の型(locとiloc、スライス、部分一致)
loc(ラベル選択)と列同時指定
row = df_id.loc[102] # 行ラベルで選ぶ
subset = df_id.loc[[101,103], ["name","score"]] # 行と列を同時に
Pythonlocは“ラベル”で選びます。インデックスを主キー化すれば、意図通りに“意味で”選択できます。
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()
Pythonlevelで階層を指定できます。マルチインデックスでは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")
Pythonis_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運用が実現できます。
