機械学習データ前処理:特定の文字列を含む行を抽出・フィルタリングする方法【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
: 欠損値を含む行はFalseと判定され、抽出されません(デフォルト)。na=True
: 欠損値を含む行はTrueと判定され、抽出されます。na=None
: 欠損値に対してエラーが発生します。
通常はデフォルトの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()
メソッドが強力なツールとなります。
機械学習モデルの性能は、与えられるデータの質に大きく依存します。データ前処理の各ステップを理解し、適切に実行できるようになることが、データ分析プロジェクト成功への鍵となります。
今後もデータ前処理に関する様々な手法を紹介していきますので、ぜひ他の記事も参考に、データ前処理スキルを習得してください。