【Pandas入門 第2回】データを自在に操る!loc, iloc, ブールインデックスを使ったデータ選択・抽出術 🔪

「DataFrameから、特定の列だけを取り出すにはどうすればいい?」
「上から3行目、左から2列目の、あのデータが欲しい!」
「年齢が30歳以上で、かつ東京在住のデータだけを絞り込みたいんだけど…」

こんにちは! Pandas探検隊、隊長のPythonistaです! 前回の第1回では、Pandasの基本的なデータ構造であるSeriesDataFrame、そしてCSVやExcelからデータを読み書きする方法を学びましたね。これで、どんな表形式データもPythonの世界に招き入れる準備が整いました。

シリーズ第2回の今回は、読み込んだデータを「スライス&ダイス」する、つまり**自由自在に部分データを選択・抽出する**ためのテクニックを徹底的に解説します! データ分析とは、まさにこの「データの中から必要な部分を見つけ出す」ことから始まります。今回は、Pandasにおけるデータ選択の3つの主要な武器、

  • ラベル名で指定する .loc
  • 行・列の番号で指定する .iloc
  • 条件に基づいてフィルタリングする ブールインデックス参照

をマスターしていきます。これらのテクニックを身につければ、巨大なデータの中からでも、あなたが必要とする情報をピンポイントで、かつ素早く取り出せるようになりますよ!


1. 準備:モジュールのインポートとサンプルDataFrameの作成

まずは、Pandasをインポートし、これからの例で使うサンプルデータフレームを作成しましょう。毎回ファイルから読み込むのは大変なので、今回はPythonの辞書から直接作成します。

import pandas as pd
import numpy as np

# サンプルデータを作成
data = {
    '名前': ['佐藤', '鈴木', '高橋', '田中', '伊藤'],
    '科目': ['数学', '英語', '数学', '理科', '社会'],
    '点数': [85, 78, 92, 88, 76],
    '評価': ['A', 'B', 'A', 'A', 'C']
}
# 's01', 's02' ... のようなカスタムインデックスを設定
student_ids = [f's0{i}' for i in range(1, 6)]
df = pd.DataFrame(data, index=student_ids)

print("--- サンプルDataFrame ---")
print(df)

実行結果:

--- サンプルDataFrame ---
      名前  科目  点数 評価
s01   佐藤  数学  85  A
s02   鈴木  英語  78  B
s03   高橋  数学  92  A
s04   田中  理科  88  A
s05   伊藤  社会  76  C

このdfというDataFrameを使って、様々なデータ選択の方法を見ていきましょう。


2. まずは基本!列の選択

特定の列のデータだけを取り出すのは、最も基本的な操作です。

2.1. 1つの列を選択する

DataFrame['列名'] のように、辞書のキーを指定する感覚で列名を書きます。結果は1次元のSeriesとして返されます。

names_series = df['名前']
print("\n--- '名前'列 (Series) ---")
print(names_series)
print(f"\n型: {type(names_series)}")

実行結果:

--- '名前'列 (Series) ---
s01     佐藤
s02     鈴木
s03     高橋
s04     田中
s05     伊藤
Name: 名前, dtype: object

型: <class 'pandas.core.series.Series'>

2.2. 複数の列を選択する

複数の列を選択する場合は、列名のリストを角括弧[]でさらに囲んで、DataFrame[['列名1', '列名2']]のようにします。この「角括弧が2つ」というのがポイントです。結果は新しいDataFrameとして返されます。

name_and_score_df = df[['名前', '点数']]
print("\n--- '名前'列と'点数'列 (DataFrame) ---")
print(name_and_score_df)
print(f"\n型: {type(name_and_score_df)}")

実行結果:

--- '名前'列と'点数'列 (DataFrame) ---
      名前  点数
s01   佐藤  85
s02   鈴木  78
s03   高橋  92
s04   田中  88
s05   伊藤  76

型: <class 'pandas.core.frame.DataFrame'>

3. 行と列を自在に選択:.loc.iloc をマスターしよう!

行を選択したり、行と列を同時に指定したりするには、.loc.ilocという2つの強力なアクセサ(アクセス手段)を使います。この2つの違いを理解することが、Pandasを使いこなす上で非常に重要です。

  • .loc[...]: **ラベル (Label)** ベースの選択。行のインデックス名と列名を文字列で指定します。
  • .iloc[...]: **整数位置 (Integer Location)** ベースの選択。行番号と列番号を0から始まる整数で指定します。PythonのリストやNumPy配列のスライシングと同じ感覚です。

3.1. ラベルで選択する .loc

# --- .loc の使い方 ---
print("\n--- .locによる選択 ---")

# 1つの行を選択 (インデックス名's02')
row_s02 = df.loc['s02']
print(f"\n行 's02':\n{row_s02}")

# 複数の行を選択 (インデックス名のリスト)
rows_s01_s04 = df.loc[['s01', 's04']]
print(f"\n行 's01', 's04':\n{rows_s01_s04}")

# ラベルでスライス (注意: locのスライスは終了ラベルも含まれる!)
rows_slice = df.loc['s02':'s04']
print(f"\n行スライス 's02'から's04'まで:\n{rows_slice}")

# 行と列を同時に指定
value = df.loc['s03', '点数']
print(f"\n's03'の'点数': {value}") # 92

# 複数行・複数列を同時に指定
sub_df = df.loc[['s01', 's05'], ['名前', '評価']]
print(f"\n's01','s05'行の'名前','評価'列:\n{sub_df}")

3.2. 行・列番号で選択する .iloc

# --- .iloc の使い方 ---
print("\n--- .ilocによる選択 ---")

# 1つの行を選択 (0から数えて1番目の行)
row_1 = df.iloc[1]
print(f"\n1番目の行:\n{row_1}") # 鈴木さんのデータ

# 複数の行を選択 (行番号のリスト)
rows_0_3 = df.iloc[[0, 3]]
print(f"\n0番目と3番目の行:\n{rows_0_3}")

# 番号でスライス (Python標準と同じで、終了番号は含まれない!)
rows_slice_iloc = df.iloc[1:4] # 1, 2, 3番目の行
print(f"\n行スライス 1から4の手前まで:\n{rows_slice_iloc}")

# 行と列を同時に指定
value_iloc = df.iloc[2, 2] # 2行目, 2列目
print(f"\n2行目, 2列目の値: {value_iloc}") # 92

# 複数行・複数列を同時に指定
sub_df_iloc = df.iloc[0:3, 0:2] # 0-2行, 0-1列
print(f"\n0-2行, 0-1列:\n{sub_df_iloc}")

まとめ: loc vs iloc

  • loc: ラベル名で指定。スライスは**終了値を含む**。
  • iloc: 整数位置で指定。スライスは**終了値を含まない**(Python標準と同じ)。

この違いをしっかり理解することが、Pandas操作のミスを減らす鍵です!


4. 条件でフィルタリング:ブールインデックス参照

データ分析の現場で最もよく使われるのが、特定の条件に合うデータだけを抽出する「フィルタリング」です。これは、NumPyでも学んだブールインデックス参照というテクニックを使います。

4.1. 基本的な条件でのフィルタリング

まず、df['列名'] > 値 のような比較演算を行うと、各行が条件を満たすかどうかがTrue/FalseSeriesとして返されます。このブールSeriesを、そのままDataFrameのインデックスとして使うことで、Trueの行だけを抽出できます。

# '点数'が80点より大きい行だけを抽出
high_scores_condition = df['点数'] > 80
print("\n--- 点数 > 80 の条件 (ブールSeries) ---")
print(high_scores_condition)

print("\n--- 点数が80点より大きいデータ ---")
high_scores_df = df[high_scores_condition]
print(high_scores_df)

# 1行で書くのが一般的
math_students_df = df[df['科目'] == '数学']
print("\n--- 科目が数学のデータ ---")
print(math_students_df)

4.2. 複数の条件を組み合わせる

複数の条件を組み合わせるには、論理演算子& (AND) と | (OR) を使います。 非常に重要な注意点:各条件式は、必ず個別の丸括弧 () で囲む必要があります!

# '科目'が数学で、かつ'点数'が90点以上のデータ
math_and_high_score_df = df[(df['科目'] == '数学') & (df['点数'] >= 90)]
print("\n--- 数学で90点以上 ---")
print(math_and_high_score_df)

# '評価'が'A'または'C'のデータ
evaluation_a_or_c_df = df[(df['評価'] == 'A') | (df['評価'] == 'C')]
print("\n--- 評価がAまたはC ---")
print(evaluation_a_or_c_df)

4.3. .isin()メソッドと否定(~)

複数のOR条件は、.isin()メソッドを使うと、より簡潔に書けます。また、条件を否定するには~演算子を使います。

# '科目'が'数学'または'理科'のデータ
subjects_to_find = ['数学', '理科']
math_or_science_df = df[df['科目'].isin(subjects_to_find)]
print("\n--- isinで数学または理科 ---")
print(math_or_science_df)

# '科目'が'数学'ではないデータ
not_math_df = df[~df['科目'].isin(['数学'])]
print("\n--- 数学ではないデータ ---")
print(not_math_df)

まとめ:これであなたもデータ選択の達人!

今回は、Pandas入門シリーズの第2回として、DataFrameから必要なデータを自由自在に取り出すための重要なテクニックを学びました。

  • 列の選択: df['列名'](Series)やdf[['列名1', '列名2']](DataFrame)。
  • .loc[]: ラベル名を使って行と列を選択する(スライスは終了値も含む)。
  • .iloc[]: 整数位置を使って行と列を選択する(スライスは終了値を含まない)。
  • ブールインデックス参照: df[条件式]の形で、条件に合うデータをフィルタリングする。& (AND) と | (OR) で複数条件もOK。

これらのデータ選択・抽出スキルは、あらゆるデータ分析作業の基礎となる、いわば「下ごしらえ」の技術です。これができなければ、データの集計も、可視化も、機械学習も始まりません。

さて、データの中から欲しいものを自在に取り出せるようになったあなた。しかし、もしそのデータに「欠けている部分(欠損値)」があったり、「間違ったデータ型」で保存されていたり、「重複したデータ」が混じっていたらどうしますか?

次回、第3回では、現実世界の「汚れた」データを綺麗にするための「データクリーニングと前処理」に挑戦します!欠損値(NaN)の扱い、データ型の変換、重複データの処理といった、データ分析の現場で必須となるスキルを学んでいきましょう。お楽しみに!

その他の投稿はこちら

コメント

このブログの人気の投稿

タイトルまとめ

これで迷わない!WindowsでPython環境構築する一番やさしい方法 #0

【Python標準ライブラリ完結!】11の冒険をありがとう!君のPython力が飛躍する「次の一歩」とは? 🚀