機械学習データ前処理入門

機械学習データ前処理:特定の文字列を含む行を抽出・フィルタリングする方法【Pandas入門】

Tags: Pandas, データ前処理, フィルタリング, 文字列処理, データ分析

はじめに

機械学習モデルの構築において、データ前処理は非常に重要なステップです。分析対象となるデータを適切に準備することで、モデルの性能を大きく向上させることができます。データ前処理の一つに、特定の条件を満たすデータを絞り込む「抽出」や「フィルタリング」があります。

特に、テキストデータを含む列や、特定のコード、IDなどの文字列データに対して、「特定の文字列を含む行だけを選びたい」というケースはよく発生します。例えば、「製品名に『限定』というキーワードを含む行だけを抽出して分析したい」「顧客のメールアドレスが特定のドメインを含む行を抽出したい」といった場合です。

本記事では、Pythonのデータ分析ライブラリであるPandasを使用して、データフレームから特定の文字列を含む行を効率的に抽出・フィルタリングする方法を、具体的なコード例とともに丁寧に解説します。プログラミング経験が少ない方でも理解できるよう、基本から説明いたします。

なぜ特定の文字列でデータをフィルタリングするのか

機械学習の前処理やデータ分析において、特定の文字列を含む行を抽出する操作は、以下のような目的で行われます。

このような操作は、データ分析の最初のステップとして、あるいはより複雑な前処理を行う前の準備段階として不可欠です。

Pandasでの文字列フィルタリング:.str.contains()メソッド

PandasのデータフレームやSeriesには、文字列操作に特化した便利な機能が用意されています。特に、特定の文字列が含まれているかを判定するために頻繁に使用されるのが、.str.contains()メソッドです。

このメソッドは、対象となるSeriesの各要素が指定した文字列(または正規表現)を含むかどうかを真偽値(True/False)で返します。この真偽値のSeriesを利用することで、データフレームから該当する行だけを抽出することができます。

基本的な使い方は以下の通りです。

データフレーム[データフレーム['対象列名'].str.contains('検索したい文字列')]

これは、「データフレーム」から、「'対象列名'列の各要素が'検索したい文字列'を含むかどうか」という条件がTrueである行だけを抽出するという意味になります。

具体的なコード例で理解する

架空の注文データを使って、.str.contains()メソッドの基本的な使い方を見ていきましょう。

まず、サンプルとなるPandasデータフレームを作成します。

import pandas as pd
import numpy as np

# サンプルデータの作成
data = {
    '注文ID': [101, 102, 103, 104, 105, 106, 107, 108, 109, 110],
    '製品名': ['ノートPC A', 'デスクトップ B', 'タブレット C (限定)', 'キーボード D', 'マウス E', 'ノートPC F', 'タブレット G', 'モニター H (限定)', 'ウェブカメラ I', 'ノートPC J'],
    'カテゴリ': ['PC', 'PC', 'タブレット', '周辺機器', '周辺機器', 'PC', 'タブレット', 'モニター', '周辺機器', 'PC'],
    '価格': [120000, 150000, 50000, 10000, 3000, 110000, 45000, 35000, 8000, 130000]
}

df = pd.DataFrame(data)

print("--- 元データ ---")
print(df)
--- 元データ ---
   注文ID           製品名   カテゴリ     価格
0   101       ノートPC A         PC 120000
1   102    デスクトップ B         PC 150000
2   103  タブレット C (限定)   タブレット  50000
3   104       キーボード D     周辺機器  10000
4   105          マウス E     周辺機器   3000
5   106       ノートPC F         PC 110000
6   107       タブレット G   タブレット  45000
7   108   モニター H (限定)     モニター  35000
8   109      ウェブカメラ I     周辺機器   8000
9   110       ノートPC J         PC 130000

基本的な文字列を含む行の抽出

「製品名」列に「ノートPC」という文字列を含む行だけを抽出してみましょう。

# 「製品名」列に「ノートPC」を含む行を抽出
filtered_df = df[df['製品名'].str.contains('ノートPC')]

print("\n--- 「ノートPC」を含む行 ---")
print(filtered_df)
--- 「ノートPC」を含む行 ---
   注文ID         製品名 カテゴリ     価格
0   101     ノートPC A      PC 120000
5   106     ノートPC F      PC 110000
9   110     ノートPC J      PC 130000

このように、df['製品名'].str.contains('ノートPC') が各行に対してTrue/Falseを判定し、その結果を使ってデータフレームをフィルタリングしています。

大文字・小文字を区別せずに抽出

デフォルトでは、.str.contains()は大文字と小文字を区別します。例えば、「限定」という文字列を含む行を抽出する場合、「(限定)」も「(L限定)」も区別されます。区別せずに検索したい場合は、case=Falseという引数を指定します。

「製品名」列に「限定」という文字列を含む行(大文字・小文字を区別しない)を抽出してみましょう。

# 「製品名」列に「限定」(大文字・小文字区別なし)を含む行を抽出
# 仮にデータに「LIMITED」なども含まれていると想定
filtered_df_case_insensitive = df[df['製品名'].str.contains('限定', case=False)]

print("\n--- 「限定」(大文字小文字区別なし)を含む行 ---")
print(filtered_df_case_insensitive)
--- 「限定」(大文字小文字区別なし)を含む行 ---
   注文ID           製品名   カテゴリ    価格
2   103  タブレット C (限定)   タブレット 50000
7   108   モニター H (限定)     モニター 35000

複数の文字列条件で抽出(OR条件)

「特定の文字列A」または「特定の文字列B」のいずれかを含む行を抽出したい場合は、.str.contains()メソッドの結果を論理和(|)で組み合わせます。

「製品名」列に「ノートPC」または「タブレット」を含む行を抽出してみましょう。

# 「製品名」列に「ノートPC」または「タブレット」を含む行を抽出
condition_pc = df['製品名'].str.contains('ノートPC')
condition_tablet = df['製品名'].str.contains('タブレット')

filtered_df_or = df[condition_pc | condition_tablet]

print("\n--- 「ノートPC」または「タブレット」を含む行 ---")
print(filtered_df_or)
--- 「ノートPC」または「タブレット」を含む行 ---
   注文ID           製品名   カテゴリ     価格
0   101       ノートPC A         PC 120000
2   103  タブレット C (限定)   タブレット  50000
5   106       ノートPC F         PC 110000
6   107       タブレット G   タブレット  45000
9   110       ノートPC J         PC 130000

複数の文字列条件で抽出(AND条件)

「特定の文字列A」かつ「特定の文字列B」の両方を含む行を抽出したい場合は、.str.contains()メソッドの結果を論理積(&)で組み合わせます。

「製品名」列に「タブレット」かつ「限定」を含む行を抽出してみましょう。

# 「製品名」列に「タブレット」かつ「限定」を含む行を抽出
condition_tablet = df['製品名'].str.contains('タブレット')
condition_limited = df['製品名'].str.contains('限定')

filtered_df_and = df[condition_tablet & condition_limited]

print("\n--- 「タブレット」かつ「限定」を含む行 ---")
print(filtered_df_and)
--- 「タブレット」かつ「限定」を含む行 ---
   注文ID           製品名   カテゴリ    価格
2   103  タブレット C (限定)   タブレット 50000

欠損値(NaN)を含む場合の注意点

対象の列に欠損値(NaN)が含まれている場合、.str.contains()メソッドはその行に対してエラーを発生させるか、意図しない結果を返す可能性があります。デフォルトでは、欠損値に対してはFalseを返します。しかし、明示的に欠損値をどのように扱うかを指定することもできます。na引数を使用します。

通常はデフォルトのna=Falseで問題ありませんが、欠損値をフィルタリングの対象に含めたい場合はna=Trueを指定します。

例として、欠損値を含むデータで確認してみましょう。

# 欠損値を含むサンプルデータの作成
data_with_nan = {
    'ID': [1, 2, 3, 4, 5],
    'テキスト': ['Apple', 'Banana', np.nan, 'Cherry', 'Date']
}
df_nan = pd.DataFrame(data_with_nan)

print("\n--- 欠損値を含む元データ ---")
print(df_nan)

# 欠損値を含む列で文字列「a」を含む行を抽出(デフォルト:na=False)
filtered_nan_default = df_nan[df_nan['テキスト'].str.contains('a', case=False)]
print("\n--- 「a」を含む行(na=False、欠損値は除外) ---")
print(filtered_nan_default)

# 欠損値を含む列で文字列「a」を含む行を抽出(na=True)
filtered_nan_true = df_nan[df_nan['テキスト'].str.contains('a', case=False, na=True)]
print("\n--- 「a」を含む行(na=True、欠損値を含む) ---")
print(filtered_nan_true)
--- 欠損値を含む元データ ---
   ID    テキスト
0   1     Apple
1   2    Banana
2   3       NaN
3   4    Cherry
4   5      Date

--- 「a」を含む行(na=False、欠損値は除外) ---
   ID  テキスト
0   1   Apple
1   2  Banana
4   5    Date

--- 「a」を含む行(na=True、欠損値を含む) ---
   ID    テキスト
0   1     Apple
1   2    Banana
2   3       NaN
4   5      Date

欠損値をどのように扱うべきかは分析や前処理の目的によりますので、状況に応じてna引数を適切に設定することが重要です。

正規表現を使ったより高度なフィルタリング

.str.contains()メソッドは、デフォルトで正規表現パターンを受け付けます。これにより、より柔軟で複雑な条件での文字列検索が可能になります。

例えば、「製品名」列で、「PC」で終わる文字列を含む行を抽出したい場合を考えます。「PC A」や「PC F」は含まれますが、「ノートPC」という単語が途中に含まれるだけでは該当しない、という条件です。正規表現では、文字列の末尾を示す$という記号を使います。

# 正規表現を使って「PC」で終わる文字列を含む行を抽出
# regex=True はデフォルトですが、明示的に指定することもできます
filtered_regex = df[df['製品名'].str.contains('PC$', regex=True)]

print("\n--- 正規表現で「PC」で終わる行 ---")
print(filtered_regex)
--- 正規表現で「PC」で終わる行 ---
   注文ID        製品名 カテゴリ     価格
0   101    ノートPC A      PC 120000
1   102   デスクトップ B      PC 150000
5   106    ノートPC F      PC 110000
9   110    ノートPC J      PC 130000

正規表現の詳細は本記事の範囲を超えるため割愛しますが、^(行頭にマッチ)、.(任意の一文字にマッチ)、*(直前の文字が0回以上繰り返される)、+(直前の文字が1回以上繰り返される)、|(OR条件)、[](文字クラス)など、様々な記号を組み合わせて強力なパターンを作成できます。

まとめ

本記事では、Pandasの.str.contains()メソッドを使用して、データフレームから特定の文字列を含む行を抽出・フィルタリングする方法を解説しました。

このメソッドを使うことで、データの中から必要な情報を効率的に絞り込むことが可能になります。基本的な文字列の一致判定だけでなく、大文字・小文字の区別、複数の条件組み合わせ、さらには正規表現を使った高度なパターンマッチングまで対応できます。

データ前処理において、特定の条件でデータを抽出・分割する操作は頻繁に行われます。特にテキスト情報を含むデータを扱う際には、今回ご紹介した.str.contains()メソッドが強力なツールとなります。

機械学習モデルの性能は、与えられるデータの質に大きく依存します。データ前処理の各ステップを理解し、適切に実行できるようになることが、データ分析プロジェクト成功への鍵となります。

今後もデータ前処理に関する様々な手法を紹介していきますので、ぜひ他の記事も参考に、データ前処理スキルを習得してください。