Pythonでデータ分析を行う際、ライブラリのPandasは欠かせないツールです。
その中でも、DataFrameやSeriesから特定のデータを抽出するための「loc」と「iloc」の使い分けは、初心者から中級者へステップアップする上で避けては通れない重要なポイントです。
一見すると似たような機能に見えるこれら2つの属性ですが、内部的な動作や指定方法は大きく異なります。
2026年現在のモダンなPandas環境においても、この違いを正確に理解していないと、意図しないデータの抽出や、予期せぬエラーに悩まされることになります。
本記事では、locとilocの根本的な違いから、実務で役立つ具体的な記述例、そしてパフォーマンスを意識した使い分けまで詳しく解説します。
locとilocの根本的な違い
Pandasのデータ抽出において、locとilocはデータの「参照の仕方」が決定的に違います。
結論から述べると、locは「ラベル(名称)」に基づいてデータを指定し、ilocは「整数(位置)」に基づいてデータを指定します。
loc(Label-based indexing)の特徴
locは、インデックス名やカラム名といった「ラベル」を直接指定してデータにアクセスします。
人間が理解しやすい名前でデータを指定するため、コードの可読性が高まるというメリットがあります。
また、locのスライシング(範囲指定)は「終点を含む」という特徴があります。
これは、Pythonの標準的なリストのスライシングとは異なる挙動であるため、注意が必要です。
iloc(Integer-positional indexing)の特徴
一方でilocは、データの論理的な位置、つまり「0から始まる行番号・列番号」を指定してアクセスします。
データフレームのラベルが何であれ、先頭から数えて何番目かという情報だけでデータを抽出します。
こちらはilocのスライシングは「終点を含まない」という、標準的なPythonの仕様(range()など)と同じ挙動を示します。
locとilocの比較まとめ
まずは、両者の主な違いを比較表で確認しましょう。
| 特徴 | loc | iloc |
|---|---|---|
| 指定方法 | ラベル名 (インデックス名、列名) | 整数位置 (0から始まるインデックス) |
| スライスの終点 | 含まれる | 含まれない |
| 条件抽出 (Boolean) | 直接利用可能 | 基本的に不可 (配列形式に変換が必要) |
| 主な用途 | 特定の名前の列・行を取得したいとき | 機械学習の訓練データ作成時など位置ベースの処理 |
具体的なコード例による解説
ここからは、実際にPandasを動かしながら、それぞれの記述方法を詳しく見ていきましょう。
まずは、サンプルとなるDataFrameを作成します。
import pandas as pd
# サンプルデータの作成
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
'Age': [25, 30, 35, 40, 45],
'City': ['Tokyo', 'Osaka', 'Nagoya', 'Fukuoka', 'Sapporo']
}
# インデックスを 'a', 'b', 'c', 'd', 'e' に設定
df = pd.DataFrame(data, index=['a', 'b', 'c', 'd', 'e'])
print(df)
Name Age City
a Alice 25 Tokyo
b Bob 30 Osaka
c Charlie 35 Nagoya
d David 40 Fukuoka
e Eve 45 Sapporo
locを使ったデータ抽出
locを使って、特定の行や列を抽出してみます。
# 'a'行のデータを取得
row_a = df.loc['a']
# 'a'行から'c'行までの 'Name' と 'Age' を取得
# 注意:'c'行も含まれる
subset_loc = df.loc['a':'c', ['Name', 'Age']]
print("--- row_a ---")
print(row_a)
print("\n--- subset_loc ---")
print(subset_loc)
--- row_a ---
Name Alice
Age 25
City Tokyo
Name: a, dtype: object
--- subset_loc ---
Name Age
a Alice 25
b Bob 30
c Charlie 35
loc['a':'c']と記述した場合、インデックスラベルが「c」である行までしっかり含まれていることがわかります。
ilocを使ったデータ抽出
次に、同じ範囲のデータをilocで抽出してみます。
# 0行目(先頭行)のデータを取得
row_0 = df.iloc[0]
# 0行目から2行目(3行目の手前)までの、0列目から1列目を取得
# 注意:インデックス2(3行目)は含まれない
subset_iloc = df.iloc[0:2, 0:2]
print("--- row_0 ---")
print(row_0)
print("\n--- subset_iloc ---")
print(subset_iloc)
--- row_0 ---
Name Alice
Age 25
City Tokyo
Name: a, dtype: object
--- subset_iloc ---
Name Age
a Alice 25
b Bob 30
iloc[0:2]の結果を見てわかる通り、指定した終点(2)は含まれず、0番目と1番目の行だけが抽出されています。
これがlocとilocの最も間違いやすい違いです。
実践的な使い分けシーン
どちらを使うべきか迷った際、判断基準となる代表的なケースを紹介します。
条件に基づく抽出(Boolean Indexing)
特定の条件に合致する行を抽出したい場合は、locを使用するのが一般的です。
# Ageが35以上の行の、'Name' と 'City' を抽出
result = df.loc[df['Age'] >= 35, ['Name', 'City']]
print(result)
Name City
c Charlie Nagoya
d David Fukuoka
e Eve Sapporo
ilocで行の条件指定を行う場合、ブール値のリストそのものは受け付けますが、カラム指定に列名(’Name’など)を使うことができません。
そのため、条件抽出にはlocが圧倒的に便利です。
データの更新
特定のセルを書き換えたい場合も、locやilocを使用します。
# ラベルを指定して更新
df.loc['a', 'Age'] = 26
# 位置を指定して更新
df.iloc[1, 1] = 31
print(df.head(2))
Name Age City
a Alice 26 Tokyo
b Bob 31 Osaka
2026年現在、Pandasでは「Chained Assignment(連鎖割り当て)」を避けることが強く推奨されています。
例えば df['Age']['a'] = 26 のような記述は、コピーに対して値を設定している可能性があり、元のデータフレームが更新されない「SettingWithCopyWarning」の原因となります。
locやilocを使って一段階でアクセスすることで、この問題を確実に回避できます。
2026年のモダンなTips:Copy-on-Writeとアクセス速度
Pandas 3.0以降、デフォルトとなったCopy-on-Write (CoW)の影響により、データの抽出効率と安全性が向上しています。
しかし、非常に大量のデータに対してループ内で1セルずつアクセスする場合、locやilocよりもさらに高速なメソッドが存在します。
スカラー値への高速アクセス:at / iat
もし、単一の要素(スカラー値)のみを取得・更新したいのであれば、at(ラベルベース)やiat(位置ベース)を利用することを検討してください。
これらはlocやilocが持つ「範囲選択機能」を削ぎ落としている分、アクセス速度が非常に高速です。
# atによる高速アクセス
age_a = df.at['a', 'Age']
# iatによる高速アクセス
age_0 = df.iat[0, 1]
print(f"Age: {age_a}, {age_0}")
Age: 26, 26
Callable(関数)による指定
locやilocの引数には、ラムダ式などの関数を渡すことも可能です。
これはメソッドチェーンの中でデータを絞り込む際に非常に役立ちます。
# メソッドチェーン内での利用例
filtered_df = (df.loc[lambda x: x['Age'] > 30]
.iloc[:, 0:2])
print(filtered_df)
Name Age
b Bob 31
c Charlie 35
d David 40
e Eve 45
注意すべき落とし穴
インデックスが整数の場合のloc
もっとも混乱を招くのは、インデックスが整数ラベルである場合です。
df_int = pd.DataFrame({'val': [10, 20, 30]}, index=[1, 2, 3])
# これはラベル「1」を探す
print(df_int.loc[1])
# これは「1番目(0から数えて)」の要素を探す、つまりラベル「2」の行
print(df_int.iloc[1])
このように、インデックスが整数の場合、loc[1]が「1番目の行」ではなく「名前が1である行」を指すため、ilocの結果とズレが生じます。
意図しない挙動を防ぐためにも、位置で指定したいなら必ずilocを使うという習慣を徹底しましょう。
存在しないラベルの指定
locで存在しないラベルを指定すると KeyError が発生します。
一方、ilocで範囲外のインデックスを指定すると IndexError が発生します。
エラーメッセージから、どちらの指定方法で失敗したかを判断する手がかりになります。
まとめ
Pandasのlocとilocは、データ抽出の基本でありながら、その違いが曖昧になりやすい要素です。
- locは「名前(ラベル)」で指定し、スライスの終点を含む。
- ilocは「番号(位置)」で指定し、スライスの終点を含まない。
- 条件抽出には
locが適しており、単一要素の高速アクセスにはatやiatが有効。
2026年現在のデータ分析現場では、コードの堅牢性と可読性が重視されます。
「なんとなく動く」コードではなく、「なぜこちらを使うのか」を明確にして使い分けることで、バグの少ないクリーンな分析コードを記述できるようになります。
まずは、自分の扱っているデータのインデックスが「名前」なのか「単なる連番」なのかを確認することから始めてみてください。
適切な選択が、効率的なデータ操作への第一歩となります。
