Shikata Ga Nai

Private? There is no such things.

11. データの前処理① 〜欠損値の扱い方〜

Hello there, ('ω')ノ

📌 1. 欠損値とは?

欠損値(Missing Value)とは、データセットの一部に「空白」や「NaN(Not a Number)」が含まれている状態 のことを指します。
例えば、以下のようなデータがあったとします。

ID 名前 年齢 性別 収入($)
1 Alice 25 女性 50,000
2 Bob NaN 男性 60,000
3 Charlie 30 NaN 55,000
4 David 35 男性 NaN

この場合、年齢・性別・収入の列に欠損値がある ことが分かります。
欠損値があると、データの分析や機械学習モデルの学習に悪影響を与える可能性があります。


📊 2. 欠損値の確認方法

まずは、データに どの列にどれくらいの欠損があるか を確認してみましょう!

✅ pandasを使った欠損値の確認

import pandas as pd

# サンプルデータの作成
data = {"Name": ["Alice", "Bob", "Charlie", "David"],
        "Age": [25, None, 30, 35],
        "Gender": ["Female", "Male", None, "Male"],
        "Income": [50000, 60000, 55000, None]}

df = pd.DataFrame(data)

# 欠損値の数を確認
print(df.isnull().sum())

出力結果(例):

Name      0
Age       1
Gender    1
Income    1
dtype: int64

df.isnull().sum() を使うと、各列の欠損値の数を確認できる!

✅ 欠損値の割合を確認

# 欠損率を計算
missing_ratio = df.isnull().sum() / len(df) * 100
print(missing_ratio)

欠損の割合を確認し、どの程度のデータが失われているか判断できる!


📌 3. 欠損値の処理方法

欠損値の処理には、大きく分けて 4つの方法 があります。

方法 メリット デメリット 適用例
① 欠損値を削除する 簡単で手軽 データが減る 欠損率が低い場合
② 平均値・中央値・最頻値で補完 シンプルで一般的 データの分布を変える可能性 数値・カテゴリ変数
③ 予測モデルで補完 高精度な補完が可能 計算コストがかかる 重要なデータの欠損
④ 特徴量エンジニアリングで活用 データを有効活用 追加の処理が必要 欠損の有無が意味を持つ場合

それぞれの方法を詳しく見ていきましょう!


✂️ 4. 欠損値を削除する

欠損値が少ない場合は、データを削除するのが最も簡単な方法です。

✅ 欠損値を含む行を削除

df_drop_rows = df.dropna()
print(df_drop_rows)

欠損値がある行(BobとDavidのデータ)が削除される!

✅ 欠損値を含む列を削除

df_drop_cols = df.dropna(axis=1)
print(df_drop_cols)

欠損の多い「Age」「Gender」「Income」の列が削除される!

欠損が少ない場合は、この方法が有効!
ただし、データが大幅に減る可能性があるので注意!


📊 5. 平均値・中央値・最頻値で補完

削除せずに 欠損値を補完 する方法もあります。

✅ 平均値・中央値で数値データを補完

import pandas as pd
import numpy as np

# 🔹 サンプルデータの作成(仮)
data = {
    "Age": [25, np.nan, 30, np.nan, 40],
    "Income": [50000, 60000, np.nan, 80000, np.nan]
}
df = pd.DataFrame(data)

# 🔹 `Age` 列の欠損値を平均値で補完(Pandas 3.0 以降推奨の方法)
df.loc[:, "Age"] = df["Age"].fillna(df["Age"].mean())

# 🔹 `Income` 列の欠損値を中央値で補完(Pandas 3.0 以降推奨の方法)
df.loc[:, "Income"] = df["Income"].fillna(df["Income"].median())

# 🔹 確認
print(df)

年齢は「平均値」、収入は「中央値」で補完される!

✅ 最頻値(mode)でカテゴリデータを補完

# 🔹 "Gender" 列の欠損値を最頻値(mode())で補完(推奨の方法)
df["Gender"] = df["Gender"].fillna(df["Gender"].mode()[0])

性別は最も多いカテゴリで補完される!

データを失わずに補完できるのがメリット!
ただし、データの分布が変わる可能性がある!


🚀 6. 機械学習モデルで補完

欠損値が多い場合、他のデータを使って予測して補完 することもできます。

import pandas as pd
from sklearn.ensemble import RandomForestRegressor

# 🔹 データの読み込み
train = pd.read_csv("/kaggle/input/titanic/train.csv")  
test = pd.read_csv("/kaggle/input/titanic/test.csv")    

# 🔹 不要な列を削除(文字列データを含む列)
drop_columns = ["Name", "Ticket", "Cabin"]
train = train.drop(columns=drop_columns)
test = test.drop(columns=drop_columns)

# 🔹 カテゴリ変数を数値に変換
train["Sex"] = train["Sex"].map({"male": 0, "female": 1})
test["Sex"] = test["Sex"].map({"male": 0, "female": 1})

# 🔹 Embarkedのワンホットエンコーディング
train = pd.get_dummies(train, columns=["Embarked"], drop_first=True)
test = pd.get_dummies(test, columns=["Embarked"], drop_first=True)

# 🔹 欠損のないデータを学習用に準備
train_data = train.dropna(subset=["Age"])  # 欠損のないデータのみ
test_data = train[train["Age"].isnull()]

# 🔹 特徴量とターゲットを分ける
X_train = train_data.drop(columns=["Age"])
y_train = train_data["Age"]

# 🔹 モデルの学習
model = RandomForestRegressor()
model.fit(X_train, y_train)

# 🔹 欠損値を予測して補完
train.loc[train["Age"].isnull(), "Age"] = model.predict(test_data.drop(columns=["Age"]))

print("✅ モデル学習完了 & Ageの補完完了")

他の特徴量を使って、より精度の高い補完が可能!
計算コストがかかるため、大規模データには向かない!


📌 7. 欠損自体を特徴量として活用

例えば、Cabin の欠損が 「キャビンを持っていない乗客」 を意味するなら、その情報を使うことができます。

# 🔹 `Cabin` 列の存在を確認
if "Cabin" in df.columns:
    df["Cabin_flag"] = df["Cabin"].notnull().astype(int)
else:
    df["Cabin_flag"] = 0  # `Cabin` 列がない場合、すべて 0 にする

欠損データを特徴量として活用することで、モデルの精度を上げられる可能性あり!


🎯 まとめ

欠損値はそのままにせず、適切に処理することが重要!
削除・統計的補完・機械学習補完などの方法がある!
状況に応じて最適な方法を選ぼう!

Best regards, (^^ゞ