一覧へ

「データクレンジング — 散らかったデータを活用できるように」

「実用的なデータにおける欠損値、重複、外れ値をどのように検出し、処理するかをpandasを使用して学びます。」

入門
|
8
|
検証済み (2026-07)
データクレンジング欠損値外れ値重複除去データ品質
進捗0/17 (0%)

データクリーニング — 質の悪いデータを活用できるようにする

このトピックを修了すると

実際のデータでよく発生する欠損値、重複、外れ値の問題を特定し、処理できるようになります。


なぜデータクリーニングが必要なのか

現実世界のデータはきれいでありません。アンケートの回答が欠けていたり、同じ人が二重に登録されていたり、年齢が-5歳になっている行があったりします。このようなデータをそのまま分析すると、結果を信頼できません。

データ分析業務の60〜80%はクリーニングに費やされると言われています。派手な分析手法よりも、この段階の方がはるかに重要です。


1段階:データの全体像を把握する

python
import pandas as pd
df = pd.read_csv("patients.csv")
# 基本情報
print(df.shape) # (1000, 8) — 1000行、8列
print(df.dtypes) # 各列のデータ型
print(df.info()) # 欠損値の状況を含む概要
# 最初/最後を確認
print(df.head()) # 上位5行
print(df.tail()) # 下位5行
# 統計概要
print(df.describe()) # 数値型の列の平均、標準偏差、最小/最大など

df.info()を実行すると、Non-Null Countが表示されます。全体の行数よりも少ない場合、欠損値があることを意味します。df.describe()でmin/maxが常識的な範囲から外れている場合、外れ値を疑います。


2段階:欠損値の処理

python
# 欠損値の確認
print(df.isnull().sum())
# name 0
# age 15
# blood_type 3
# weight 42
# 戦略1:削除 — 欠損行が少数の場合
df_clean = df.dropna(subset=["blood_type"]) # blood_typeがない3行を削除
# 戦略2:補完 — 数値型の列
df["age"] = df["age"].fillna(df["age"].median()) # 中央値で
df["weight"] = df["weight"].fillna(df["weight"].mean()) # 平均で
# 戦略3:特定の値で補完
df["blood_type"] = df["blood_type"].fillna("未確認")

どの戦略を使用するかは、状況によって異なります。

  • 欠損率が5%未満であれば、削除が最も安全です。
  • 数値型は、中央値(外れ値に強い)または平均で補完します。
  • カテゴリ型(血液型、性別)は、最頻値または「未確認」で補完します。

3段階:重複の削除

python
# 重複の確認
print(df.duplicated().sum()) # 23個の重複行
# 重複の内容を表示
print(df[df.duplicated(keep=False)]) # 元の行 + 重複する行すべてを表示
# 重複の削除(最初の行を保持)
df = df.drop_duplicates()
# 特定の列を基準に重複を削除
df = df.drop_duplicates(subset=["patient_id"], keep="last")

keep="first"は、最初の行を保持し、残りを削除します。keep="last"は、最後の行を保持します。データが時間順であれば、lastが最新のレコードを残します。


4段階:外れ値の検出

python
# 基本的な統計で確認
print(df["age"].describe())
# min: -5 ← 異常
# max: 200 ← 異常
# 範囲フィルタリング
df = df[(df["age"] >= 0) & (df["age"] <= 120)]
# IQR法 — 統計的な外れ値の検出
Q1 = df["weight"].quantile(0.25)
Q3 = df["weight"].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
outliers = df[(df["weight"] < lower) | (df["weight"] > upper)]
print(f"外れ値 {len(outliers)}個を検出")
# 外れ値の削除
df = df[(df["weight"] >= lower) & (df["weight"] <= upper)]

外れ値を無条件に削除すべきではありません。年齢-5は明らかなエラーなので削除しますが、体重150kgは実際に存在する可能性があります。ドメイン知識が外れ値の判断の鍵です。


5段階:型の変換と形式の統一

python
# 文字列で表現された数字 → 数値型に変換
df["age"] = pd.to_numeric(df["age"], errors="coerce")
# 日付文字列 → datetime型に変換
df["visit_date"] = pd.to_datetime(df["visit_date"])
# 文字列の整理 — 前後の空白、大文字小文字の統一
df["name"] = df["name"].str.strip()
df["blood_type"] = df["blood_type"].str.upper()

errors="coerce"は、変換できない値(例:"N/A")をNaNで処理します。エラーを出さずに処理できるため、大量のデータに便利です。


重要なまとめ

段階確認事項主要なツール
全体像の把握行/列数、型、欠損状況info()describe()
欠損値割合の確認 → 削除 or 補完isnull()fillna()dropna()
重複同じ行またはキーを基準とした重複duplicated()drop_duplicates()
外れ値常識的な範囲 + IQRdescribe()、範囲フィルタリング
型/形式数字、日付、文字列の統一to_numeric()to_datetime()str.strip()

データクリーニングは反復的で退屈な作業ですが、この段階を省略すると、その後のすべての分析結果が揺らぎます。「Garbage in, garbage out」 — 入力がゴミであれば、出力もゴミになります。

💬 質問・コメント

0件のコメント

ログインせずに投稿できます。ゲスト投稿は投稿者自身で編集・削除できません。

0/2000

読み込み中...