「インデックスとして読む」とは何をしているのか
pandas の DataFrame には「行番号」を表すインデックスがあります。
何も指定しないと 0,1,2,3,… という単なる連番ですが、
「日付」や「ID」など、意味のある列をインデックスにしておくと、
行の指定・絞り込み・結合がぐっと書きやすくなります。
index_col=0 は、「0番目の列をインデックスとして使う」という指定です。
Excelの一番左の列を、そのまま行ラベルにするイメージです。
基本形:index_col=0 の挙動を理解する
最小コードと動きのイメージ
import pandas as pd
df = pd.read_excel("sales.xlsx", index_col=0)
print(df.head())
print(df.index)
Pythonこのとき、Excel の一番左の列(0番目の列)が DataFrame のインデックスになります。
つまり、その列は「普通の列」ではなくなり、df["その列名"] ではなく df.index から参照する形になります。
例えば、左端が「日付」のシートなら、読み込んだ瞬間から「日付がインデックスの DataFrame」になります。
どんな列をインデックスにすると嬉しいか
日付をインデックスにするパターン
時系列データでは、「日付をインデックス」にしておくと、期間指定が直感的に書けます。
import pandas as pd
df = pd.read_excel(
"daily_sales.xlsx",
parse_dates=["Date"],
index_col="Date" # 列名で指定する書き方
)
print(df.head())
print(df.index)
Pythonこの状態だと、例えばこういう書き方ができます。
# 2025年1月だけ
jan = df["2025-01-01":"2025-01-31"]
# 2025年3月以降
after_mar = df["2025-03-01":]
Pythonindex_col=0 ではなく index_col="Date" を使うと、
「どの列をインデックスにしているか」がコードから一目でわかるので、実務ではこちらをおすすめします。
ID・コードをインデックスにするパターン
顧客IDや商品コードなど、「行を一意に識別するキー」がある場合も、インデックスにしておくと便利です。
import pandas as pd
df = pd.read_excel(
"customers.xlsx",
dtype={"CustomerID": "string"},
index_col="CustomerID"
)
print(df.head())
print(df.index)
Pythonこうしておくと、特定の顧客を取り出すのが直感的になります。
customer = df.loc["C000123"]
Pythonインデックスにしていない場合は、毎回 df[df["CustomerID"] == "C000123"] のように書く必要があります。
「よくキーとして使う列」は、インデックスにしておく価値が高いです。
index_col=0 と他の引数の組み合わせ
header や skiprows と一緒に使う
先頭にタイトル行などがある場合、skiprows で飛ばしてから index_col を指定します。
import pandas as pd
df = pd.read_excel(
"report.xlsx",
skiprows=4, # 5行目からが表
header=0, # 5行目をヘッダーに
index_col=0 # 一番左の列をインデックスに
)
print(df.head())
print(df.index)
Pythonここで大事なのは、「index_col は『ヘッダーが決まった後の列番号』で数える」ということです。skiprows や header の結果、どの列が 0 番目になっているかを意識してください。
usecols と一緒に使うときの注意
usecols で列を絞ると、「0番目の列」が変わります。
例えば、こういうコードを考えます。
df = pd.read_excel(
"sales.xlsx",
usecols=["Date", "Product", "Amount"],
parse_dates=["Date"],
index_col=0
)
Pythonこの場合、usecols で指定した中の 0 番目、つまり Date 列がインデックスになります。
「左から何番目」ではなく、「usecols で残した中の何番目」になる点に注意してください。
列名で指定すると、こういうズレを避けられます。
df = pd.read_excel(
"sales.xlsx",
usecols=["Date", "Product", "Amount"],
parse_dates=["Date"],
index_col="Date"
)
Python実践テンプレートでイメージを固める
テンプレ1:日付インデックスの売上データを読み、期間で絞り込む
import pandas as pd
df = pd.read_excel(
"daily_sales.xlsx",
usecols=["Date", "Amount"],
parse_dates=["Date"],
index_col="Date"
)
df["Amount"] = pd.to_numeric(df["Amount"], errors="coerce")
# 2025年1月だけ
jan = df["2025-01-01":"2025-01-31"]
# 2025年上半期
first_half = df["2025-01-01":"2025-06-30"]
print(jan.head())
print(first_half.tail())
Pythonここでは、「日付でスライスする」書き方が自然に使えています。
インデックスが単なる 0,1,2,… のままだと、こういう書き方はできません。
テンプレ2:顧客IDをインデックスにして、特定顧客の情報をすぐ引けるようにする
import pandas as pd
df = pd.read_excel(
"customer_master.xlsx",
dtype={"CustomerID": "string"},
index_col="CustomerID"
)
print(df.loc["C000123"])
Pythonこのテンプレートは、「マスタ系の表」を扱うときに非常に便利です。loc で一発で行を引けるので、検索や結合のコードが短くなります。
つまずきやすいポイントと注意点
インデックスに欠損や重複があると扱いづらい
インデックスは「行ラベル」なので、本来は一意であることが望ましいです。
欠損(NaN)や重複が多い列をインデックスにすると、loc での取得がややこしくなります。
「この列は本当にキーとして使えるか?」
「欠損や重複はないか?」
を一度確認してからインデックスにするのが安全です。
print(df.index.isna().sum())
print(df.index.duplicated().sum())
Pythonindex_col=0 を安易に使うと「意図しない列」がインデックスになる
index_col=0 は「一番左の列」をインデックスにしますが、
その列が本当にインデックスにしたい列かどうかは、ファイルごとに違います。
実務では、できるだけ列名で指定する方が安全です。
index_col="Date"
index_col="CustomerID"
Python「左端だからインデックス」ではなく、「キーとして使いたいからインデックス」という発想で選んでください。
小さな練習問題
練習1:daily_sales.xlsx を「日付インデックス」で読み、2025年3月だけを抽出する
条件は次の通りです。
usecols=["Date", "Amount"]を使うparse_dates=["Date"]で日付型にするindex_col="Date"で日付をインデックスにする"2025-03-01":"2025-03-31"でスライスして表示する
自分で書いてみて、df.index の型と、抽出結果を確認してみてください。
練習2:customers.xlsx を「CustomerID インデックス」で読み、特定IDの行を取り出す
条件は次の通りです。
dtype={"CustomerID": "string"}を指定するindex_col="CustomerID"を指定する- 任意のID(例:
"C000001")の行をlocで取り出して表示する
ここまでできると、「インデックスを設計して読み込む」という感覚がかなり身についてきます。
最後に
index_col=0(あるいは index_col="列名")は、
「この表の行ラベルは何か?」を読み込み時に決めるためのスイッチです。
日付やIDのような「軸」になる列をインデックスにしておくと、
- 期間指定やキー指定のコードが短くなる
- 結合や検索が直感的になる
- DataFrame の構造が「人間の感覚」に近づく
という大きなメリットがあります。
「この表の行を識別するのに、一番しっくりくる列はどれか?」
それを一度考えてから index_col を決める癖をつけると、データの扱い方が一段レベルアップします。
