機械学習データ前処理:条件でデータを絞り込み、その値を変更する方法【Pandas入門】
機械学習モデルの性能を高めるためには、データの品質が非常に重要です。データ前処理では、欠損値の処理や重複データの削除など様々な工程がありますが、その中でも特定の条件を満たすデータの値を修正する作業は、実際のビジネスデータでは頻繁に必要になります。
例えば、入力ミスによって特定のコードが誤って記録されている場合や、あるしきい値以下の売上データを「ゼロ」として扱う場合などです。このようなデータに対して適切な修正を行わないと、機械学習モデルが間違ったパターンを学習してしまい、分析結果や予測精度に悪影響を及ぼします。
この記事では、Pythonのデータ分析ライブラリであるPandasを使って、特定の条件を満たすデータの値を効率的に変更する方法を、具体的なコード例とともに解説します。非エンジニアの方でも理解できるよう、基本的な考え方から丁寧に説明します。
なぜ条件でデータを修正する必要があるのか
実世界のデータは完璧ではありません。以下のような様々な理由で、特定の条件に合致するデータを修正する必要が生じます。
- 入力エラーの修正: 人手によるデータ入力やシステム連携の際に発生した誤りを訂正する。
- ビジネスルールの適用: 特定の条件(例: 一定期間活動がない顧客)を満たすデータを、ビジネス上の定義(例: 「休眠顧客」としてフラグを立てる、または関連数値をゼロにする)に基づいて更新する。
- 異常値の処理: 明らかに異常な値(例: 売上がマイナス、年齢が200歳)を特定し、削除、置き換え、またはフラグ付けなどの対応を行う。
- データの標準化: 複数のデータソースで表記が揺れている情報(例: 都道府県名の略称、会社名の正式名称)を統一する際に、条件に基づいて修正を行う。
- 分析目的でのデータの整形: 特定の分析を行うために、データを集計したり、新しい特徴量を作成したりする過程で、条件に応じた値の変換が必要になる。
これらの作業を手作業で行うと、時間と労力がかかるだけでなく、ミスも発生しやすくなります。Pandasを使えば、これらの修正作業を効率的かつ再現可能に行うことができます。
Pandasを使った条件によるデータ修正の基本
Pandasでは、データフレームから特定の条件を満たす行や列を抽出する際に []
や .loc
, .iloc
といった機能を使用します。これらの機能は、データを抽出するだけでなく、抽出した部分に対して新しい値を代入することでデータの修正にも利用できます。
ここでは、最も一般的で推奨される .loc
を使用した方法を中心に解説します。.loc
は、ラベル(行インデックス名、列名)に基づいてデータを指定するための機能ですが、条件式と組み合わせることで非常に強力なデータ修正ツールになります。
基本的な構文は以下のようになります。
df.loc[条件式, 修正したい列名] = 新しい値
df
: 対象となるPandasデータフレーム条件式
: Pandasシリーズとして真偽値(True/False)を返す式。Trueとなる行が修正対象になります。修正したい列名
: 値を変更したい列の名前を指定します。単一の列名を指定することも、複数の列名をリストで指定することも可能です。新しい値
: 条件を満たすすべての場所に代入したい値を指定します。この値は単一の値でも、条件を満たす行数と同じ長さのシリーズや配列でも構いません。
具体的なコード例で学ぶデータ修正
架空の売上データを使って、様々な条件でのデータ修正方法を見ていきましょう。
まず、サンプルデータフレームを作成します。
import pandas as pd
import numpy as np
# サンプルデータフレームの作成
data = {
'商品ID': ['A001', 'A002', 'A003', 'A001', 'A004', 'A002', 'A005', 'A003'],
'店舗': ['東京', '大阪', '名古屋', '福岡', '東京', '大阪', '福岡', '東京'],
'売上金額': [1200, 800, 3500, 150, 5000, 950, 200, 4000],
'数量': [10, 5, 20, 1, 30, 6, 2, 25],
'備考': ['正常', '割引適用', '大口', '不良品', '正常', 'キャンペーン', '不良品', '正常']
}
df = pd.DataFrame(data)
print("元データフレーム:")
print(df)
元データフレーム:
商品ID 店舗 売上金額 数量 備考
0 A001 東京 1200 10 正常
1 A002 大阪 800 5 割引適用
2 A003 名古屋 3500 20 大口
3 A001 福岡 150 1 不良品
4 A004 東京 5000 30 正常
5 A002 大阪 950 6 キャンペーン
6 A005 福岡 200 2 不良品
7 A003 東京 4000 25 正常
例1: 特定の列の値を特定の条件で変更する
「備考」列が「不良品」となっている行の「売上金額」をゼロに修正することを考えます。
修正したい条件は df['備考'] == '不良品'
です。
修正したい列は '売上金額'
です。
新しい値は 0
です。
これを .loc
を使って表現します。
# 条件を満たす行の特定の列の値を修正
df.loc[df['備考'] == '不良品', '売上金額'] = 0
print("\n修正後データフレーム (例1):")
print(df)
修正後データフレーム (例1):
商品ID 店舗 売上金額 数量 備考
0 A001 東京 1200 10 正常
1 A002 大阪 800 5 割引適用
2 A003 名古屋 3500 20 大口
3 A001 福岡 0 1 不良品
4 A004 東京 5000 30 正常
5 A002 大阪 950 6 キャンペーン
6 A005 福岡 0 2 不良品
7 A003 東京 4000 25 正常
「不良品」の行(インデックス3と6)の「売上金額」がゼロに変更されていることがわかります。
例2: 数値列を対象に、しきい値に基づいて値を変更する(閾値処理)
「売上金額」が500円未満のデータを、低売上として「売上金額」をNaN(欠損値)に変更し、「数量」もゼロに修正することを考えます。(元の売上金額が150円、200円のデータが対象となります)
条件は df['売上金額'] < 500
です。
修正したい列は '売上金額'
と '数量'
です。
新しい値は、「売上金額」には np.nan
、「数量」には 0
をそれぞれ代入します。
複数の列を修正する場合は、修正したい列名をリストで指定し、新しい値も対応する値をリストやシリーズで指定します。今回は異なる値を代入するため、それぞれの列に対して個別に代入を行うか、あるいは新しい値をシリーズとして指定します。ここでは、それぞれの列に対して個別に代入する例を示します。
# 条件を満たす行の複数の列の値を修正
condition = df['売上金額'] < 500
df.loc[condition, '売上金額'] = np.nan # 売上金額をNaNに
df.loc[condition, '数量'] = 0 # 数量を0に
print("\n修正後データフレーム (例2):")
print(df)
修正後データフレーム (例2):
商品ID 店舗 売上金額 数量 備考
0 A001 東京 1200.0 10 正常
1 A002 大阪 800.0 5 割引適用
2 A003 名古屋 3500.0 20 大口
3 A001 福岡 NaN 0 不良品
4 A004 東京 5000.0 30 正常
5 A002 大阪 950.0 6 キャンペーン
6 A005 福岡 NaN 0 不良品
7 A003 東京 4000.0 25 正常
※ Pandasでは、NaNが含まれる数値列は自動的に浮動小数点型(float)になるため、「売上金額」が 1200.0
のようになっています。
条件を満たす行(元々売上金額が150円と200円だった行、インデックス3と6)の「売上金額」がNaN、「数量」が0に変更されていることがわかります。
例3: 複数の条件を組み合わせてデータを修正する
例えば、「店舗」が「東京」または「大阪」であり、かつ「数量」が10以上の商品の「備考」欄に「要チェック」と追記することを考えます。
条件1: df['店舗'] == '東京'
条件2: df['店舗'] == '大阪'
条件3: df['数量'] >= 10
これらの条件を組み合わせるには、論理演算子 &
(AND) と |
(OR) を使用します。各条件式は ()
で囲む必要があります。
複合条件: ((df['店舗'] == '東京') | (df['店舗'] == '大阪')) & (df['数量'] >= 10)
修正したい列は '備考'
です。
新しい値は、既存の値に「(要チェック)」を追記した文字列です。これは、修正対象となる行の既存の「備考」列の値を取得し、それに文字列を追加するという操作になります。
# 複数の条件を組み合わせたデータ修正
condition_complex = ((df['店舗'] == '東京') | (df['店舗'] == '大阪')) & (df['数量'] >= 10)
# 条件を満たす行の「備考」列に追記
# 新しい値は、条件を満たす行の元の「備考」列の値に依存します。
df.loc[condition_complex, '備考'] = df.loc[condition_complex, '備考'] + '(要チェック)'
print("\n修正後データフレーム (例3):")
print(df)
修正後データフレーム (例3):
商品ID 店舗 売上金額 数量 備考
0 A001 東京 1200.0 10 正常(要チェック)
1 A002 大阪 800.0 5 割引適用
2 A003 名古屋 3500.0 20 大口
3 A001 福岡 NaN 0 不良品
4 A004 東京 5000.0 30 正常(要チェック)
5 A002 大阪 950.0 6 キャンペーン
6 A005 福岡 NaN 0 不良品
7 A003 東京 4000.0 25 正常(要チェック)
「店舗」が東京かつ数量10以上の行(インデックス0, 4, 7)の「備考」欄に「(要チェック)」が追記されていることがわかります。(大阪かつ数量10以上の行はありませんでした)
このように、条件式と .loc
を組み合わせることで、複雑な条件に基づいたデータ修正も柔軟に行うことができます。
条件による修正時の注意点
SettingWithCopyWarning
: Pandasでデータフレームの一部を抽出した「ビュー」に対して操作を行うと、意図しない挙動や警告(SettingWithCopyWarning
)が発生することがあります。.loc
をdf.loc[条件式, 列名] = 新しい値
の形式で使う場合は、多くの場合この警告を回避できます。一時的にデータフレームの一部を抽出して、その抽出したデータフレームに対して別の操作を行う際に発生しやすいため、基本的には.loc
を使った代入構文を推奨します。- 条件式の確認: 複雑な条件式を書いた場合は、実際に修正を行う前に
df[条件式]
のようにして、意図したデータが正しく選択されているかを確認することが重要です。 - 元のデータのバックアップ: 大量のデータを修正する前には、万が一の失敗に備えて元のデータをコピーしておくと安全です(
df.copy()
)。
まとめ
この記事では、機械学習のためのデータ前処理において、特定の条件を満たすデータの値をPandasを使って効率的に修正する方法を解説しました。
- 実世界のデータに存在する様々な問題に対処するためには、条件に基づいたデータ修正が必要であること。
- Pandasの
.loc
を条件式と組み合わせて使うことで、データの抽出だけでなく値の変更も行えること。 - 単一の条件、複数の列、複数の条件を組み合わせた修正方法を具体的なコード例で確認しました。
条件によるデータ修正は、データの品質を向上させ、機械学習モデルがより正確な学習を行うための重要なステップです。今回紹介したPandasの基本的なテクニックを習得することで、ご自身のデータをより効果的に前処理できるようになるはずです。
次のステップとしては、さらに複雑な条件処理や、特定のパターン(正規表現など)を使った文字列データの条件付き修正などについても学んでいくと良いでしょう。