Python

ilocの使い方|pandasで行・列を抽出、locとの違いも解説

pandasのilocは、データフレーム(DataFrame)やシリーズ(Series)から、行や列を位置(整数のインデックス番号)で抜き出すためのアクセサです。書き方はdf.iloc[行, 列]で、行も列も0から数えます。列名や行ラベルで取り出すlocと対になる存在で、どちらを使うかは「番号で指定したいか、名前で指定したいか」で決まります。

この記事では、ilocの基本構文から、locとの違い、行・列それぞれの抽出、.iloc[-1]での最終行取得、つまずきやすいエラーの回避までを、すべて実行できるコード付きで解説します。サンプルには次のDataFrameを使います。

import pandas as pd

df = pd.DataFrame({
    '名前': ['佐藤', '鈴木', '田中', '高橋', '伊藤'],
    '年齢': [28, 34, 45, 23, 39],
    '部署': ['営業', '開発', '人事', '開発', '営業'],
    '年収': [420, 560, 680, 380, 510],
})
# 行インデックスは 0,1,2,3,4 、列は 名前,年齢,部署,年収 の順

まとめ:ilocの基本構文と早見表

先に結論を整理します。ilocは「位置(整数)で行・列を取り出す」アクセサで、よく使う書き方は次の通りです。番号で取りたいときはiloc、名前で取りたいときはlocと覚えておけば、ほとんどの場面で迷いません。

やりたいこと 書き方 戻り値
0行目を取得 df.iloc[0] Series(その行)
最終行を取得 df.iloc[-1] Series(最後の行)
1〜2行目を取得 df.iloc[1:3] DataFrame(3は含まない)
0・2・4行目を取得 df.iloc[[0, 2, 4]] DataFrame
1列目(年齢)を取得 df.iloc[:, 1] Series(その列)
1行2列目の値 df.iloc[1, 2] スカラー値('開発')

ilocは整数位置だけを受け付けます。スライスの終端を含まない点、範囲外指定でのエラー、ブール条件の扱いが主なつまずきどころなので、後半で個別に押さえます。pandas自体の役割を先に把握したい場合はPython Pandasで何ができるのかもあわせて参照してください。

ilocとは:位置(整数)で行と列を抽出する仕組み

ilocはinteger-location(整数位置)の略で、行や列を0始まりの番号で指定します。DataFrameに対してはdf.iloc[行番号, 列番号]、Seriesに対してはs.iloc[要素番号]と書きます。データフレームの背後にあるNumPy配列を位置で参照する感覚に近く、行名や列名が何であっても番号さえ合っていれば取得できます。配列の位置指定そのものの考え方はNumPyの読み方と基本的な使い方で扱っています。

# 1行目(番号1=鈴木の行)をSeriesで取得
print(df.iloc[1])
# 名前    鈴木
# 年齢    34
# 部署    開発
# 年収    560
# Name: 1, dtype: object

# 1行目・2列目(部署)の単一値を取得
print(df.iloc[1, 2])
# 開発

列だけ、行だけを取りたいときは、片方をコロン:(全選択)にします。df.iloc[:, 1]なら全行の1列目(年齢)、df.iloc[2]なら2行目の全列です。インデックスを振り直したDataFrameでも、ilocは見た目の並び順(位置)で取得するため、並べ替え後の「上からn番目」を確実に取り出せます。

ilocとlocの違い:位置指定とラベル指定、スライス終端の扱い

ilocとlocは指定の基準が異なります。ilocは位置(整数)、locはラベル(行名・列名)です。初期状態の連番インデックスでは番号とラベルが一致するため違いが見えにくいですが、スライスの終端の扱いで明確に分かれます。

観点 iloc loc
指定の基準 位置(整数, 0始まり) ラベル(行名・列名)
列の指定 列番号 列名(文字列)
スライスの終端 含まない(排他) 含む(包括)
主な用途 並び順のn番目を取る 名前で確実に取る
# iloc は終端を含まない(0,1 の2行)
print(df.iloc[0:2])
#    名前  年齢  部署   年収
# 0  佐藤  28  営業  420
# 1  鈴木  34  開発  560

# loc は終端を含む(0,1,2 の3行)
print(df.loc[0:2])
#    名前  年齢  部署   年収
# 0  佐藤  28  営業  420
# 1  鈴木  34  開発  560
# 2  田中  45  人事  680

使い分けの基準ははっきりしています。列名や行ラベルが分かっていればloc「上から3番目」のように位置で取りたければilocです。条件式(ブール)でのフィルタはlocの担当で、ilocには向きません(後述)。番号とラベルを混在させたい場合だけ、片方を変換してから揃えます。

ilocで行を抽出する:単一・複数・スライス・最終行

行の取得はilocの最頻ユースケースです。単一行はSeries、複数行はDataFrameで返ります。負のインデックスが使えるため、行数を数えなくても末尾から取り出せます。

# 単一行(0行目)→ Series
df.iloc[0]

# 最終行 → 末尾から1番目。行数が変わっても常に最後を指す
df.iloc[-1]
# 名前    伊藤 ... Name: 4

# 連続した範囲(1,2行目。3は含まない)
df.iloc[1:3]

# 飛び飛びの複数行はリストで指定(0,2,4行目)
df.iloc[[0, 2, 4]]

df.iloc[-1]は「最終行だけ確認したい」「時系列の最新レコードを取りたい」ときの定番です。先頭n行はdf.iloc[:n]、末尾n行はdf.iloc[-n:]で取れるため、head()tail()と違って取得位置を式で細かく制御できます。単一行を取り出すとSeriesになり列名がインデックスへ移る点だけ、後続処理で意識しておきます。

ilocで列を抽出する:単一列・複数列・範囲指定

列を取り出すときは、行側をコロン:で全選択し、列側を番号で指定します。「pandasで特定の列だけ抽出したい」という場面はlocで列名指定する方法が一般的ですが、列の並び順が決まっているならilocの番号指定が簡潔です。

# 単一列(1列目=年齢)→ Series
df.iloc[:, 1]

# 複数列をリストで(0列目=名前, 2列目=部署)
df.iloc[:, [0, 2]]

# 列の範囲(1〜2列目=年齢,部署。3は含まない)
df.iloc[:, 1:3]

# 先頭2行 × 先頭2列のブロックを切り出す
df.iloc[0:2, 0:2]

列番号は左から0で数えます。列の追加や並べ替えで番号がずれると別の列を取得してしまうため、列構成が変わりうるデータではlocの列名指定のほうが安全です。逆に、前処理で列順を固定したパイプラインなら、ilocの番号指定が読みやすく速度面でも軽量です。

行と列を同時に指定する:交差抽出と単一値の高速取得

行と列を同時に渡すと、その交差部分を取り出せます。範囲・リスト・整数を行側と列側で自由に組み合わせられます。

# 1行2列目の単一値
df.iloc[1, 2]            # '開発'

# 0〜2行 × 0〜1列のブロック
df.iloc[0:3, 0:2]

# 飛び飛びの行と列を同時に(0,2行目 × 1,3列目)
df.iloc[[0, 2], [1, 3]]

単一のセル値だけが欲しいときは、ilocよりもiatが軽量です。pandas公式はiatを「単一の値を取得・設定する場合に使う」アクセサと位置づけており、範囲やリストの解釈を伴わないぶんアクセスのオーバーヘッドが小さくなります。df.iloc[1, 2]df.iat[1, 2]は同じ値を返すため、ループ内で大量のセルを1つずつ読む処理ではiatに置き換える効果が出やすい書き方です。範囲やリストを渡す一般的な抽出はiloc、単一セルの読み書きはiat、と覚えておくと選択に迷いません。

ilocで起きやすいエラーと注意点

ilocのつまずきは、ほぼ「位置指定のルール」に起因します。エラーの種類ごとに原因と回避策を分けて押さえます。

範囲外指定によるIndexError(single positional indexer is out-of-bounds)

存在しない位置を単一の整数で指定するとIndexError: single positional indexer is out-of-boundsが発生します。「インデックスが配列の境界外」という趣旨のエラーで、行数5のDataFrameにdf.iloc[10]のような指定をしたときに起きます。回避するには、len(df)で行数を確認するか、末尾を取りたいだけならdf.iloc[-1]を使います。なお、スライス指定(df.iloc[3:100]など)は範囲外でもエラーにならず、存在する分だけ返る点が単一指定との違いです。

スライスは終端を含まない(オフバイワン)

ilocのスライスはPython標準と同じく終端を含みません。df.iloc[0:5]は0〜4行目の5行で、5行目は入りません。locのdf.loc[0:5]が0〜5の6行を返すのと混同しやすいので、「iloc=終端の手前まで」と覚えます。最後の要素まで含めたいときは、終端を1つ大きくするか、スライスを省略してdf.iloc[2:]のように書きます。

ブール条件での抽出はilocではなくlocの役割

df.iloc[df['年齢'] > 30]」のように条件式(ブールSeries)を渡すと、ilocは位置指定を期待するためエラーになります。条件でのフィルタはdf[df['年齢'] > 30]またはdf.loc[df['年齢'] > 30]を使います。なお、ilocが受け付けないのはラベル付きのブールSeriesであって、長さの一致するブール配列(リストやNumPy配列)は渡せます。下記はどちらも0・2・4行目を返します。旧来「ilocはブール非対応」と説明されることがありますが、正確には「条件式(Series)は不可、ブール配列は可」です。

# NG: 条件式(ブールSeries)はエラー
# df.iloc[df['年齢'] > 30]

# OK: 条件抽出は通常のブールインデックスか loc
df[df['年齢'] > 30]
df.loc[df['年齢'] > 30]

# OK: 長さ一致のブール配列なら iloc でも可
df.iloc[[True, False, True, False, True]]

値の代入とSettingWithCopyWarning(pandas 3.0のCopy-on-Write)

取得だけでなく代入もできますが、df.iloc[行, 列] = 値のように1回のiloc呼び出しで位置を指定して代入するのが原則です。df[df['年収'] > 500].iloc[0, 0] = '更新'のような連鎖(チェーン)した代入は、コピーに書き込んでしまいSettingWithCopyWarningが出たり、元データに反映されないことがあります。pandas 3.0ではCopy-on-Write(CoW)が既定になり、この連鎖代入の挙動が変わりました。バージョンによって結果が異なるため、代入時の動作はCopy-on-Write(CoW)とは?Pandasの動作変更に見る基本概念で確認し、必ず単一のiloc/loc呼び出しで代入してください。

データ分析でのiloc実践例

位置指定は、機械学習やデータ前処理で「順番が意味を持つデータ」を扱うときに効きます。代表的な使い方を挙げます。

# 先頭・末尾の確認(行数に依存しない)
df.iloc[:3]     # 先頭3行
df.iloc[-3:]    # 末尾3行

# 訓練データとテストデータを位置で分割(先頭4件:残り)
train = df.iloc[:4]
test = df.iloc[4:]

# 特徴量(説明変数)と目的変数を列位置で分ける
X = df.iloc[:, :-1]   # 最終列を除く全列
y = df.iloc[:, -1]    # 最終列(年収)

とくにX = df.iloc[:, :-1]y = df.iloc[:, -1] は、最終列を目的変数に置いたデータで頻出する書き方です。列名を逐一書かずに「最後の列=正解ラベル」という前提だけで分割でき、列が増減してもコードを変えずに済みます。時系列データで「直近n件だけ学習に使う」といった位置ベースの切り出しも、ilocが最も素直に書けます。

よくある質問

ilocとlocはどちらを使うべきですか?

行名・列名(ラベル)が分かっていてそれで指定したいならloc、並び順の「上からn番目」を位置で取りたいならilocです。条件式でのフィルタはloc(または通常のブールインデックス)の担当で、ilocには渡せません。連番インデックスのままなら両者の結果は近くなりますが、スライスの終端の扱い(ilocは含まない、locは含む)だけは必ず異なります。

.iloc[-1]で最終行だけ取得するにはどうしますか?

df.iloc[-1]で最終行をSeriesとして取得できます。行数を数える必要はなく、行が増減しても常に最後の行を指します。最終行をDataFrameの形のまま残したい場合はdf.iloc[[-1]]とリストで囲みます。末尾n行ならdf.iloc[-n:]です。

df.iloc[条件式]でエラーになるのはなぜですか?

ilocは整数の位置を期待するアクセサのため、df['年齢'] > 30のようなラベル付きブールSeriesを渡すと位置として解釈できずエラーになります。条件抽出はdf[df['年齢'] > 30]df.loc[...]を使ってください。どうしてもilocで条件を使うなら、長さの一致するブール配列(.to_numpy()でラベルを外す等)に変換します。

ilocとiatの違いは何ですか?

どちらも整数位置でアクセスしますが、iatは単一のセル値(スカラー)専用で高速、ilocは単一値に加えて範囲・リスト・複数行列の抽出に対応する汎用アクセサです。df.iloc[1, 2]df.iat[1, 2]は同じ値を返すため、1セルだけを大量に読み書きする処理ではiatに置き換えると速くなります。

特定の列だけ抽出するにはどう書きますか?

ilocなら行側をコロンで全選択し、df.iloc[:, 1](単一列)やdf.iloc[:, [0, 2]](複数列)と書きます。列の並び順が固定なら番号指定が簡潔です。列名で取りたい場合はdf.loc[:, '年齢']df[['名前', '部署']]のほうが、列の追加・並べ替えに強くなります。

関連記事

資料請求

RELATED POSTS 関連記事