PandasのDataFrameからデータを選択する際、locとilocのどちらを使用すべきか迷うことはよくあると思います。一見似ていますが、ラベルベースと整数位置ベースという根本的に異なる動作原理を理解していないと、意図しない結果やエラーにつながります。本記事では、学生の成績データを例に、両者の核心的な違いと実践的な使い分けを解説します。詳細は元記事もご参照ください。

基本概念:ラベル(loc) vs 位置(iloc)
locは**行と列のラベル(名前)に基づいてデータを選択します。一方、ilocは行と列の整数位置インデックス(0始まり)**を使用します。この違いが全てを決定します。
まずはサンプルのDataFrameを準備し、インデックスを設定してみましょう。
import pandas as pd
# サンプルデータの作成
data = {
'student_id': [101, 102, 103, 104, 105],
'name': ['Alice', 'Bob', 'Charlie', 'Diana', 'Edward'],
'math': [85, 58, 92, 76, 88],
'english': [90, 64, 78, 81, 95],
'science': [92, 70, 85, 79, 91]
}
df = pd.DataFrame(data)
# 'student_id'をインデックスに設定
df.set_index('student_id', inplace=True)
print(df)
次に、locとilocを使って同じデータ(Bobの情報)を抽出してみます。
# locを使用: ラベル(102)で選択
bob_loc = df.loc[102]
print("locの結果:")
print(bob_loc)
print()
# ilocを使用: 位置(1)で選択 (インデックスは0から始まる)
bob_iloc = df.iloc[1]
print("ilocの結果:")
print(bob_iloc)
結果は同じBobのデータが出力されますが、選択のロジックが異なります。locはラベルが102の行を探し、ilocは単純に2行目(位置1)を取得します。

実務でよく使われるパターン
1. 複数行・列の選択
ラベルまたは位置のリストを渡すことで、複数の要素を選択できます。
# loc: ラベルリストで複数の学生を選択
selected_loc = df.loc[[101, 103, 105]]
# iloc: 位置リストで複数の学生を選択
selected_iloc = df.iloc[[0, 2, 4]]
2. スライシングにおける重要な違い
スライシングでは、locは終了ラベルを含み、ilocは終了位置を含みません(標準のPythonスライシングと同じ)。
# loc スライシング (101から103までを'含む')
sliced_loc = df.loc[101:103]
# iloc スライシング (0から3まで、位置3は'含まない')
sliced_iloc = df.iloc[0:3]
この違いを理解していないと、データをチャンクに分割する際に重複や抜けが発生する可能性があるため注意が必要です。
3. ブーリアンフィルタリング
条件に合致する行をフィルタリングする場合は、locの方がはるかに直感的です。
# 数学の点数が80点以上の学生
high_math = df.loc[df['math'] > 80]
# 数学 > 70 かつ 科学 > 80 の学生
high_scores = df.loc[(df['math'] > 70) & (df['science'] > 80)]
ilocで同じことを行うには、ブーリアンSeriesをリストに変換する面倒な作業が必要になります。

まとめ:結局、いつどちらを使うべき?
locを使うべき場合: DataFrameに意味のあるラベル(学生ID、日付など)があり、そのラベルに基づいてデータを選択・フィルタリングしたいとき。コードの可読性が重要で、ブーリアンフィルタリングが必要なとき。ilocを使うべき場合: ラベルがない、または意味をなさないとき(単なる0,1,2...)。データの絶対的位置(最初の100行、最後の10行など)に関心があるとき。ラベルが重複したり変更される可能性があり、堅牢な位置ベースのコードが必要なとき。
locは「名前で呼ぶ」、ilocは「番号で呼ぶ」と考えるとわかりやすいでしょう。データの特性と作業目的に応じて適切なツールを選択する習慣を身につけることで、Pandasを使ったデータ操作の効率と精度が大きく向上します。ぜひ実際にコード例を実行して、感覚を掴んでみてください。