Pandas .loc[] と .iloc[] を使った行の選択(単一・複数・スライス)

こんにちは。前回は、Pandas DataFrameから分析に必要な「列」を選択する様々な方法([], .loc, .iloc)について学びました。これで、表の中から縦方向の情報を取り出すスキルが身につきましたね。

今回は、DataFrameの操作におけるもう一つの重要な軸、「行」の選択に焦点を当てます。データ分析では、「特定の期間のデータだけ見たい」「上位3件の結果だけ表示したい」「特定の条件に合致するサンプルだけを取り出したい」といったように、特定の行を選び出す場面が非常に多くあります。

この記事では、Pandasで特定の行を選択するための主要な方法である.loc[].iloc[]の使い方を徹底的に解説します。この2つは非常に強力ですが、使い分けが少しややこしく、初心者が混乱しやすいポイントでもあります。

この記事を読むことで、あなたは以下のことができるようになります。

  • .loc[]を使ったラベル(インデックス名)基準での行選択方法を理解する(単一、複数、範囲指定)。
  • .iloc[]を使った整数位置(0からの順番)基準での行選択方法を理解する(単一、複数、範囲指定)。
  • .loc[].iloc[]根本的な違い(ラベルか位置か)と、それぞれの使い分けのポイントを明確に理解する。
  • スライス(範囲指定)時の終端の扱い.loc[].iloc[]で異なる点を把握する。
  • 行選択の結果がSeriesになるかDataFrameになるかを理解する。

今回も具体的なサンプルデータとコードを使って、それぞれの操作がどのようにデータに作用するのかを、目で見て確認しながら進めていきます。.loc[].iloc[]をしっかり区別して使いこなせるようになれば、Pandasでのデータ操作が格段にスムーズになりますよ!

なぜ行選択が必要なのか?

前回、列選択の重要性について触れましたが、行選択も同様にデータ分析において不可欠な操作です。

  • データの絞り込み: 何千、何万とあるデータの中から、分析対象となる特定の期間、特定のグループ、あるいは特定の条件に合致するデータだけを取り出すことができます。(※条件による絞り込みは次回詳しく扱いますが、その基礎となるのが行選択です)
  • 順序に基づく抽出: データの先頭部分(head()の代わり)、末尾部分(tail()の代わり)、あるいは特定の位置にあるデータ(例:3番目のデータ)をピンポイントで取り出すことができます。
  • サンプリング: 大規模なデータセットから一部の行をランダムに(または規則的に)抽出して、小さなサンプルデータを作成し、分析の試行やモデルのテストに使うことができます。
  • 特定の行への操作: 特定の行の値を更新したり、削除したりする前処理にも、まずその行を選択する必要があります。

サンプルデータの準備

今回も、分かりやすさのために、これまでの記事で使ってきた社員情報のサンプルデータを使用します。このDataFrameは、デフォルトで0から始まる整数のインデックスを持っています。これが.loc.ilocを理解する上で重要になります。

import pandas as pd

# サンプルデータをPythonの辞書で作る
data = {
    '社員ID': ['S001', 'S002', 'S003', 'S004', 'S005', 'S006', 'S007'],
    '氏名': ['佐藤 一郎', '鈴木 花子', '高橋 健太', '田中 優子', '伊藤 次郎', '渡辺 直美', '山本 翔太'],
    '部署': ['営業部', '開発部', '営業部', '人事部', '開発部', '営業部', '開発部'],
    '年齢': [35, 28, 41, 31, 25, 38, 29],
    '経験年数': [10, 5, 15, 8, 2, 12, 6],
    '評価スコア': [4.5, 4.8, 4.2, 4.0, 4.9, 3.8, 4.6]
}

# 辞書データからDataFrameを作成
df = pd.DataFrame(data)

# 作成したDataFrameを表示(インデックスに注目!)
print(df)

実行結果(インデックスを確認してください):

  社員ID     氏名   部署  年齢  経験年数  評価スコア
0  S001  佐藤 一郎  営業部  35    10     4.5
1  S002  鈴木 花子  開発部  28     5     4.8
2  S003  高橋 健太  営業部  41    15     4.2
3  S004  田中 優子  人事部  31     8     4.0
4  S005  伊藤 次郎  開発部  25     2     4.9
5  S006  渡辺 直美  営業部  38    12     3.8
6  S007  山本 翔太  開発部  29     6     4.6

一番左の太字の数字(赤色で強調)がインデックスです。今回は0, 1, 2, 3, 4, 5, 6という連番になっています。.loc.ilocはこのインデックスをどう扱うかが異なります。

.loc[] : ラベル(インデックス名)でアクセスする

.loc[]は、「ラベル」に基づいてデータを選択します。行に関して言えば、「インデックスの名前(ラベル)」を使って行を指定します。

今回のサンプルデータでは、インデックスの名前(ラベル)がたまたま0, 1, 2, ...という整数になっています。しかし、インデックスは文字列(例えば’A’, ‘B’, ‘C’)や日付など、他のタイプの値を持つこともあります。.loc[]は、インデックスがどのような型の値であっても、その名前(表示されている値そのもの)を使ってアクセスします。

単一の行を選択: df.loc[行ラベル]

1つの行だけを選択するには、.loc[]の中にその行のインデックスラベルを指定します。

例えば、インデックスラベルが2の行(高橋 健太さんのデータ)を選択してみましょう。

# インデックスラベルが2の行を選択
row_loc_2 = df.loc[2]
print(row_loc_2)

実行結果:

社員ID        S003
氏名        高橋 健太
部署          営業部
年齢            41
経験年数          15
評価スコア       4.2
Name: 2, dtype: object

インデックスラベルが2の行のデータが抽出されました。この結果は、Series形式になります。左側が列名、右側がその行における値です。Seriesの名前(Name: 2)には、選択した行のインデックスラベルが入ります。データ型がobjectと表示されているのは、このSeries内に数値と文字列が混在しているためです。

複数の行を選択: df.loc[[行ラベル1, 行ラベル2]]

複数の行を選択するには、.loc[]の中に選択したい行ラベルのリストを渡します。

例えば、インデックスラベルが1(鈴木 花子さん)と5(渡辺 直美さん)の行を選択してみましょう。

# インデックスラベルが1と5の行を選択
rows_loc_1_5 = df.loc[[1, 5]]
print(rows_loc_1_5)

実行結果:

  社員ID    氏名   部署  年齢  経験年数  評価スコア
1  S002  鈴木 花子  開発部  28     5     4.8
5  S006  渡辺 直美  営業部  38    12     3.8

指定した2つの行が抽出され、結果はDataFrame形式になります。リストで指定した順番(この場合は1, 5)で行が表示されます。

行の範囲を選択(スライス): df.loc[開始ラベル:終了ラベル]

連続した範囲の行を選択するには、スライス記法開始ラベル:終了ラベルを使います。

例えば、インデックスラベルが2から4までの行を選択してみましょう。

# インデックスラベルが2から4までの行を選択
rows_loc_2_to_4 = df.loc[2:4]
print(rows_loc_2_to_4)

実行結果:

  社員ID     氏名   部署  年齢  経験年数  評価スコア
2  S003  高橋 健太  営業部  41    15     4.2
3  S004  田中 優子  人事部  31     8     4.0
4  S005  伊藤 次郎  開発部  25     2     4.9

インデックスラベルが2, 3, 4の行が選択されました。結果はDataFrame形式です。

.locのスライスで最も重要な注意点:
.loc[開始ラベル:終了ラベル]を使ったスライスでは、終了ラベルで指定した行も含まれるということです。上の例では、終了ラベルとして4を指定しましたが、結果にはインデックスが4の行も含まれていますね。これは、Pythonの通常のリストスライス(終了位置は含まない)とは異なる挙動なので、特に注意が必要です。

.iloc[] : 整数位置(0からの順番)でアクセスする

.iloc[]は、「整数による位置(順番)」に基づいてデータを選択します。行に関して言えば、「上から何番目か(0から数えて)」という情報を使って行を指定します。

.iloc[]は、インデックスのラベルが何であるか(数値か文字列かなど)には関係なく、常に0から始まる行の順番でアクセスします。

単一の行を選択: df.iloc[行の整数位置]

1つの行だけを選択するには、.iloc[]の中にその行の整数位置(0からの順番)を指定します。

例えば、上から3番目の行(インデックスラベルは2ですが、順番としては0, 1, 2番目)を選択してみましょう。指定する整数位置は2です。

# 上から3番目(整数位置2)の行を選択
row_iloc_2 = df.iloc[2]
print(row_iloc_2)

実行結果:

社員ID        S003
氏名        高橋 健太
部署          営業部
年齢            41
経験年数          15
評価スコア       4.2
Name: 2, dtype: object

df.loc[2]と同じ行が選択されましたが、その理由は異なります。.loc[2]は「インデックスラベルが2の行」を選び、.iloc[2]は「上から数えて(0から数えて)2番目の行」を選んでいます。今回はインデックスラベルと順番が一致しているため、同じ結果になりました。結果の形式はSeriesです。

複数の行を選択: df.iloc[[整数位置1, 整数位置2]]

複数の行を選択するには、.iloc[]の中に選択したい行の整数位置のリストを渡します。

例えば、上から2番目(整数位置1)と6番目(整数位置5)の行を選択してみましょう。

# 上から2番目(整数位置1)と6番目(整数位置5)の行を選択
rows_iloc_1_5 = df.iloc[[1, 5]]
print(rows_iloc_1_5)

実行結果:

  社員ID    氏名   部署  年齢  経験年数  評価スコア
1  S002  鈴木 花子  開発部  28     5     4.8
5  S006  渡辺 直美  営業部  38    12     3.8

df.loc[[1, 5]]と同じ行が選択されました(これもインデックスラベルと順番が一致しているため)。結果はDataFrame形式です。

行の範囲を選択(スライス): df.iloc[開始位置:終了位置]

連続した範囲の行を選択するには、スライス記法開始位置:終了位置を使います。

例えば、上から3番目(整数位置2)から5番目(整数位置4)の手前までの行を選択してみましょう。終了位置は5を指定します。

# 上から3番目(整数位置2)から5番目(整数位置4)までの行を選択
rows_iloc_2_to_4 = df.iloc[2:5]
print(rows_iloc_2_to_4)

実行結果:

  社員ID     氏名   部署  年齢  経験年数  評価スコア
2  S003  高橋 健太  営業部  41    15     4.2
3  S004  田中 優子  人事部  31     8     4.0
4  S005  伊藤 次郎  開発部  25     2     4.9

整数位置が2, 3, 4の行が選択されました。結果はDataFrame形式です。

.ilocのスライスで最も重要な注意点:
.iloc[開始位置:終了位置]を使ったスライスは、通常のPythonのリストスライスと同様に、終了位置で指定した番号の行は含まれません。上の例では、終了位置として5を指定しましたが、結果には整数位置が4の行までしか含まれていませんね。これは、終了ラベルを含む.locのスライスとは逆の挙動であり、最も混同しやすいポイントです!

.loc.iloc のスライスの違い(最重要!)

  • df.loc[開始ラベル:終了ラベル] : 終了ラベルの行を含む
  • df.iloc[開始位置:終了位置] : 終了位置の行を含まない

.loc と .iloc の使い分け – どちらを使うべき?

.loc.iloc、どちらも行を選択できますが、根本的な違いはアクセス方法です。

  • .loc[]: ラベル(インデックス名)でアクセスする。インデックスが文字列や日付でも、その表示されている名前で指定する。
  • .iloc[]: 整数位置(0からの順番)でアクセスする。インデックスのラベルが何であっても、常に上からの順番で指定する。

どちらを使うべきかは、状況や目的によって異なります。

.loc[] を使うのが適している場合:

  • インデックスに意味のある名前(日付、ID、カテゴリ名など)がついている場合。ラベルで指定する方が直感的で分かりやすい。
  • コードの可読性を重視したい場合。ラベル名の方が、単なる番号よりも意味が伝わりやすいことが多い。
  • データの並び順が変わっても、特定のラベルを持つ行を確実に選択したい場合。

.iloc[] を使うのが適している場合:

  • インデックスのラベルに関係なく、単純に「何番目の行」という位置でアクセスしたい場合。
  • DataFrameの先頭N行や末尾N行を選択したい場合(スライスを使う)。
  • ループ処理などで、行番号を順番に使ってアクセスしたい場合。
  • インデックスラベルが複雑だったり、重複していたりする場合(位置で指定する方が確実なことがある)。

初心者の皆さんへのおすすめ:
まずは、両者の違い(ラベル vs 位置)をしっかり理解することが最優先です。
今回のサンプルのようにインデックスが0からの連番の場合、.loc[i].iloc[i]が同じ結果になるため、違いを意識しにくいかもしれません。しかし、インデックスが異なる場合(例えば、DataFrameを並べ替えた後など)は、両者の結果は全く異なるものになります。

基本的な使い方としては、

  • インデックスのラベル名が分かっている場合は.loc[]を使うことを基本とする。
  • インデックスに関係なく位置で指定したい場合に.iloc[]を使う

という方針で始めると、混乱が少ないかもしれません。そして、スライスを使う際は、終端を含むか含まないかの違いを常に意識するようにしましょう。

まとめ

今回は、Pandas DataFrameから特定の「行」を選択する主要な方法である.loc[].iloc[]について、その違いと使い方を詳しく学びました。

  • .loc[]ラベル(インデックス名)基準でアクセスします。
    • 単一行: df.loc[ラベル] (結果はSeries)
    • 複数行: df.loc[[ラベル1, ラベル2]] (結果はDataFrame)
    • 範囲(スライス): df.loc[開始ラベル:終了ラベル] (終了ラベルを含む, 結果はDataFrame)
  • .iloc[]整数位置(0からの順番)基準でアクセスします。
    • 単一行: df.iloc[位置] (結果はSeries)
    • 複数行: df.iloc[[位置1, 位置2]] (結果はDataFrame)
    • 範囲(スライス): df.iloc[開始位置:終了位置] (終了位置を含まない, 結果はDataFrame)
  • 両者の最も重要な違いは「ラベルでアクセスするか、位置でアクセスするか」であり、特にスライス時の終端の扱いが逆である点に注意が必要です。
  • どちらを使うかは状況によりますが、まずは違いを理解し、ラベルが明確な場合は.loc[]を基本とするのがおすすめです。

行選択は、列選択と並んでPandasのデータ操作の基本中の基本です。これらの操作を組み合わせることで、DataFrameの中から必要な情報を自在に取り出すことができるようになります。

次回予告

これまで、列の選択、行の選択(ラベル/位置基準)を個別に学んできました。しかし、データ分析で最も頻繁に行うのは、「特定の条件を満たす行」を抽出することかもしれません。

次回は、いよいよ条件式を使って行をフィルタリング(抽出)する方法を解説します。例えば、「部署が営業部の行だけ」「年齢が30歳以上の行だけ」「評価スコアが4.5以上、かつ開発部の行だけ」といった、より実践的なデータの絞り込みテクニックを学びます。これができるようになると、データ分析の幅が一気に広がりますよ!お楽しみに!