🔖 キーワード索引
30秒結論文脈直感数式読み解き実値計算Python実装落とし穴比較表産業活用演習FAQ参考文献用語辞典50連発欠損補完外れ値
「データクレンジング (data cleansing)」は欠損値・外れ値・重複・表記揺れ・型不整合・桁ズレなど "データ品質の欠陥" を体系的に検出・修正する工程。 分析パイプラインの土台であり、 GIGO (Garbage In, Garbage Out) を回避する最初の防衛線。 本ページでは欠損補完・外れ値判定 (IQR/Z-score)・重複削除・正規化・dtype 修正の標準手順を SSDSE-B-2026 で順に追う。
欠損値検出 isnull/dropna外れ値 IQR / Z-score重複 duplicated表記揺れ str.normalizedtype 修正 astypeSSDSE-B-2026 47県pandera スキーマ検証Great ExpectationsGIGO 回避
これらのキーワードは「品質欠陥の検出 → 修正方針の決定 → スキーマ検証で再発防止」というデータクレンジングの標準フローを構成する。
💡 30秒で分かる結論
🍰 まずはやさしく
データの汚れを落とす掃除のような作業です。
正しい分析結果を出すために使います。
アンケートの書き間違いを直すようなことです。
この章ではデータの整え方について読みます。
不整合・誤りなどを修正してデータを整える処理
- 分野:データ処理 — 📚 データエンジニアリング
- 用途:分析・前処理・モデル構築・解釈支援などの場面で使われます
- 注意:適用条件と限界を理解してから使うのが鉄則
データクレンジング を 30 秒で把握する重要ポイント:
- 何ができるか: 欠損・外れ値・重複・表記揺れ・型不整合を検出・修正し、 分析に耐える品質に整える。 分析の "前処理の前処理" であり、 結論の信頼性を根本から左右する。
- いつ使うか: 生データを EDA・モデリングに渡す前、 およびスキーマが変わる度に再実施。 SSDSE のように官製の整備済データでも、 結合キー揃え・dtype 検証は必須。
- 注意点: 欠損を闇雲に dropna しない (MCAR/MAR/MNAR の見極めが先)、 外れ値削除は「ドメイン上ありえない値」のみに限定、 表記揺れは Unicode NFKC で機械的に統一。
- 関連: 欠損値 / 外れ値 / データガバナンス / ETL をセットで学ぶと現場 OPS に直結する。
📍 あなたが今見ているもの
🍰 まずはやさしく
分析を始める前の準備段階のことです。
きれいなデータを作るために使います。
スマホで集めたデータのゴミを取り除く例です。
この章では具体的な修正の手順を読みます。
本ページは用語集の 「データ前処理」大分類 に属し、 直上には データエンジニアリング という上位概念がある。 データクレンジング(Data Cleansing)はその第一工程で、 データ収集 の直後・欠損値処理/詳細クレンジング/データ結合 の直前に位置する。
入口:CSV を pd.read_csv() で読んだら欠損やゴミが見えた、 という場面。 出口:「分析に渡せるきれいな DataFrame」を作る。 次の章でやること:SSDSE-B-2026 で実際に「末尾空白の列名」「『-』のまま残った欠損」「全角/半角混在」を検出し、 strip()/replace()/astype()/drop_duplicates() で修復する手順を 1 つずつ実演する。
🎨 直感で掴む
🍰 まずはやさしく
散らかった部屋を片付ける作業に似ています。
作業しやすい環境を作るために使います。
部活の名簿で名前の書き方を揃えるようなことです。
この章では間違いを見つけて直す方法を読みます。
データクレンジングは「分析する前に、 欠損・重複・表記揺れ・型のズレ・外れ値を整える掃除作業」。 SSDSE-B-2026 のような公式統計でも、 列名末尾の空白や「-」のまま残った欠損が混じり、 そのまま集計するとピボット結果がずれる。 プロジェクト工数の 60-80% を占めると Forbes / Anaconda の調査が繰り返し報告する地味だが決定的な工程である。
以下では、 SSDSE-B-2026 の都道府県データに混じる末尾空白の列名・「-」のままの欠損・全角/半角の表記揺れを実際に検出するコードから始め、 strip()・replace()・astype()・drop_duplicates() を用いた修復手順、 そして「Excel で開いて壊した CSV を Python で再現性なく修復してしまう」「対症療法的に fillna(0) して分析を歪める」といった現場の落とし穴まで順に辿ります。
データクレンジングは 「散らかった部屋を片付けて作業机を確保する」 作業に喩えるとよい。 SSDSE-B-2026 を素のまま読み込むと、 列名末尾に空白、 欠損が空文字列、 同じ「東京都」が「東京」「Tokyo」に揺れているなど、 そのままでは集計関数が誤った答えを返す状態が混じる。 これらを整える 6 つの典型操作は 欠損補完・型変換・重複削除・表記統一・外れ値処理・スキーマ整合 の 6 操作で、 通常はこの順序でパイプライン化する。
クレンジングは「分析の前段」と位置付けられがちだが、 実プロジェクトでは全工数の 60-80% を占めることが Forbes・Anaconda の調査で繰り返し報告されている。 SSDSE は公式が整備済みのため比較的綺麗だが、 それでも年度間で列名が変わったり (R02_population → P_population)、 一部都道府県で値が「-」のまま放置されている等、 細かな整形は避けられない。
クレンジング処理は 「元に戻せること」 が鉄則: 元 CSV は data/raw/ に置いたままにし、 処理後を data/processed/ に書き出す。 これにより「外れ値除去のせいで沖縄の値が消えていた」のような事故を後から検証できる。 Python では pandas の chain 形式 df.dropna().assign(...).rename(...) でステップを可視化、 大規模では Great Expectations や Pandera で 品質ゲート を CI に組み込む。
🔬 数式を言葉で読み解く
| 操作 | 意味 | SSDSE-B-2026 での具体例 |
| $T_\text{cast}$ | 型変換(文字列 → 数値・日付) | 年度 を int32 に固定 |
| $T_\text{rename}$ | 列名統一 | 総人口 → pop_total |
| $T_\text{impute}$ | 欠損補完 | 都道府県平均で穴埋め(SSDSE-C 用) |
| $T_\text{outlier}$ | 外れ値処理 | 東京の人口を別フラグで保持しつつ統計化 |
| $T_\text{dedup}$ | 重複削除 | (年度, 都道府県) で drop_duplicates |
| $T_\text{unit}$ | 単位正規化 | 床面積を「m²」「ha」「km²」で揃える |
| $T_\text{trim}$ | 前後空白・全角空白除去 | 都道府県名の str.strip() |
| $T_\text{join}$ | 結合・正規化 | 地域コードを別マスタと結合 |
🔬 深掘り: クレンジングの設計原理 7 段
クレンジングは「とりあえず NaN を落とす」 だけの作業ではない。 本節では、 実務で何度も悩む 7 つの判断ポイントを、 SSDSE-B-2026 を題材に整理する。 ここを押さえれば、 自分のチームのクレンジング規約をゼロから書ける。
① 「行を削るか・列を削るか」 を最初に決める
欠損が「特定の数列に集中」 しているなら列削除、 「特定の数行に集中」 しているなら行削除が原則。 SSDSE-B-2026 自体は悉皆調査で欠損ゼロだが、 一般に欠損が数列に集中している場合は、 まず「その列を使うかどうか」 を業務要件と照らして判断する。 行と列を同時に削るのは情報を失いすぎるためアンチパターン。
② 「補完するか・しないか」 は分散歪みのコストで決める
平均代入は分散を縮め、 標準誤差を過小評価する。 多重代入 (MICE) は分散を保つが計算コスト・解釈コストが高い。 「探索的分析の段階」 では補完せず欠損のまま、 「モデル投入の直前」 で初めて MICE か KNN 補完を行うのが現代的。 SSDSE-B-2026 では欠損が無いため、 補完を行う必然性は低い。
③ 「外れ値 = 異常」 ではない
出生数 (A4101) や人口 (A1101) で IQR の上限を超えるのは、 東京・大阪・愛知など「大都市の構造的特性」。 これを「異常」 として削除すると、 SSDSE-B-2026 が捉えるべき重要な現象 (人口や出生の大都市集中) を捨ててしまう。 外れ値処理は必ず「ドメイン知識による判定」 を組み合わせる。
④ クレンジングは「順番」 が結果を左右する
正しい順序は「① 重複削除 → ② 型変換 → ③ 欠損処理 → ④ 外れ値処理」。 例えば欠損を平均で埋めた後に外れ値判定をすると、 平均が引き寄せられて判定基準が歪む。 SSDSE-B-2026 のような公的統計でも、 後段の派生指標を作るときにこの順序を間違えると結論が変わる。
⑤ クレンジングログは「列名 + 削除理由 + 件数」 を残す
「何件削った」 だけでは再現できない。 「列 A1101 で IQR 3 倍を超えた 3 行を確認のうえ保持、 列 X で NaN だった 12 行を削除」 のように、 列・理由・件数を必ず記録する。 SSDSE-B-2026 のような公的データでも、 自分のチームのフィルタ条件は完全に文書化する。
⑥ クレンジング後の検証は「分布の前後比較」 で行う
削除前後で平均・中央値・分散・最頻値が大きく動いていないかを確認する。 大きく動いた場合、 「削除が過剰だった」 か「重要な構造を捨てた」 可能性が高い。 SSDSE-B-2026 では、 クレンジング前後で「人口の中央値が 10% 以上動いたら警戒」 という運用基準が現場で使われる。
⑦ クレンジングは「コード」 として再現可能に
Excel での手動編集ではクレンジングが再現できず、 「翌年の更新時に同じ品質が保てない」 という問題を引き起こす。 必ず Python スクリプトとして残し、 引数で「データバージョン」 を切り替えられる構造にする。 SSDSE 系は毎年更新されるため、 再現可能なクレンジングが特に重要。
❓ よく聞かれる質問 (R516 追補 10 問)
本ページに対して、 講義・社内勉強会・実務支援の現場でよく頂く質問を 10 件、 SSDSE-B-2026 に即して回答する。 既存の FAQ 20 問と合わせて 30 件分の Q&A になる。
Q11. 欠損補完で平均と中央値、 どちらが安全?
右に長い分布 (人口、 所得など) では中央値の方が安全。 SSDSE-B-2026 の人口は右に長いため、 平均代入は実際より高い値で埋めることになる。 ただし「補完したことを記録する」 のは必須。
Q12. クレンジング前後で結果が変わったらどう判断?
「クレンジングが結果を変えた」 のではなく「クレンジングが結果を正した」 か「クレンジングが過剰だった」 のどちらかを判定する。 中央値・分散の変化幅を見て、 ドメイン知識と照合する。
Q13. 外れ値は削除すべき、 補正すべき、 保持すべきのどれ?
原則は保持。 削除は「明らかな入力誤り」 と判定できるときのみ。 補正 (Winsorization) は分析の都合で「分布の裾を切る」 必要があるときに限定的に使う。
Q14. SSDSE-B-2026 で重複行は本当にない?
「年度 × 都道府県」 を主キーとすれば 0 行。 ただし「コード A1101 と A1101_万人」 のような派生列が増えると、 列方向の重複が混入することがある。 値の重複ではなく列の重複も確認する。
Q15. クレンジングの所要時間の目安は?
分析プロジェクト全体の 60〜80% を占めると言われる。 SSDSE-B-2026 のような整備済みデータでも、 単位統一・派生列作成・型統一に 1〜2 日は確保するのが現実的。
Q16. ChatGPT 等の LLM にクレンジングを任せていい?
「列名と意味の対応付け」 「ルール抽出のたたき台」 までは有効。 ただし最終判定はドメイン知識を持つ人が必ず確認する。 LLM は「単位の違い」 「カテゴリの粒度」 を取り違えやすい。
Q17. クレンジングルールはチームで共有すべき?
必須。 「同じデータ × 違うクレンジング」 で報告書の数字が違うと、 後工程の信頼を一気に失う。 SSDSE-B-2026 のような公開データでも、 派生列の定義を組織内で標準化する価値は高い。
Q18. 「クレンジング」 と「前処理」 の違いは?
クレンジングは「データそのものの品質を上げる」 工程、 前処理はクレンジング後に「モデル投入に適した形に整える」 (標準化・エンコーディング・特徴量設計) 工程。 どちらか一方ではなく、 順番に通すのが正しい。
Q19. SSDSE-B-2026 で最も注意すべき列は?
経済系の指標 (A4101 等)。 「絶対額」 と「1 人あたり」 の混在、 単位 (千円・百万円) の違いがある。 列名の説明書を必ず読み、 派生列に「単位サフィックス」 を付けて運用する。
Q20. クレンジングの自動化はどこまで進められる?
「欠損率の計算」 「重複検出」 「型変換」 までは完全自動化できる。 ただし「外れ値の最終判定」 「列削除の判断」 はドメイン知識が要るため、 ルールベース + 人間レビューが現実解。
🛠 実務ワークフロー詳説: SSDSE-B-2026 を一通りクレンジングする 9 ステップ
ここでは SSDSE-B-2026 のような時系列パネルデータを実務でクレンジングする際の標準ワークフローを 9 ステップに分けて解説する。 各ステップで「やること」 「使う関数」 「品質基準」 「失敗パターン」 を明示し、 自分のプロジェクトでそのまま流用できる形に整理する。 最後の検収まで通せば、 同僚や上司に渡しても恥ずかしくないクレンジング結果になる。
ステップ 1: データの一次取り込みとスキーマ確認
最初に pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8-sig') でデータを取り込み、 df.shape df.dtypes df.columns の 3 点を必ず確認する。 「行数 564、 列数 112」 という公的なスキーマと一致しないなら、 ファイル損傷や読み込みエンコーディング誤りを疑う。 BOM 付き UTF-8 で書かれているため utf-8-sig を使うのがコツ。 ここで間違えると以後の処理がすべて狂う。
ステップ 2: 主キーの定義と重複チェック
「年度 × 都道府県」 を主キーと定め、 df.duplicated(subset=['年度','都道府県']).sum() でゼロを確認する。 もし 1 件でも重複があれば、 取り込みの段階で集計ミスが入っている。 SSDSE-B-2026 は整備済みのため通常はゼロだが、 自前で派生ファイルを作った場合は再確認する。 主キーをはっきり決めずに分析を進めると、 後で 2 倍計算などの致命的ミスにつながる。
ステップ 3: 型変換と単位の標準化
数値列は pd.to_numeric(errors='coerce') で float64 に統一、 カテゴリ列 (都道府県・地域ブロック) は astype('category') でカテゴリ型にする。 単位は「人」 と「万人」 が混在しがちなので、 派生列に _人 _万人 のサフィックスを付けて両方持つのが現代的。 後段で「単位を間違えてグラフを描いた」 という事故が起きにくくなる。
ステップ 4: 欠損の可視化と対応方針決定
列ごとに df.isna().mean() を計算し、 棒グラフで降順に並べる (missingno ライブラリを使うとさらに見やすい)。 SSDSE-B-2026 は悉皆調査で欠損ゼロだが、 一般に欠損が数列に集中する場合は、 「その列を使うか・捨てるか」 を業務要件と照合する。 単純削除は避け、 欠損フラグ列を作って後段で「欠損だったことを覚えておく」 のが推奨。 欠損は「データの語り」 でもあるからだ。
ステップ 5: 外れ値の検出と扱い決定
人口・所得など右に長い分布の列は np.log1p で対数変換してから IQR 法を適用する。 上位 5 件が東京・大阪・愛知・神奈川・福岡なら「都市の特殊性」 として保持、 それ以外なら入力ミスを疑う。 削除か Winsorization か対数変換のままモデル投入か、 を業務目的別に決める。 「外れ値が異常値とは限らない」 という原則をチームで共有する。
ステップ 6: 派生列の生成と命名規約
「1 人あたり所得」 「高齢化率」 「合計特殊出生率」 など、 分析の主役となる派生列を作る。 命名規約は「元列名 + 単位サフィックス」 が最も保守しやすい。 派生列はメモリ消費を増やすが、 後段の分析・グラフ生成での誤解を激減させる。 命名規約は SSDSE のように年次更新があるデータでは特に重要。
ステップ 7: 整合性検証 (相互チェック)
派生列同士の整合性を assert で検証する。 例えば「1 人あたり所得 × 人口 = 総所得」 が成立すべきなのに ±1% 以上ズレるなら、 どこかで丸めや単位ミスが起きている。 SSDSE-B-2026 のような統合データでは整合性検証が特に効果的。 検証スクリプトをリポジトリに含めて、 CI で毎回回すのが理想。
ステップ 8: クレンジングログの保存
「何を、 なぜ、 何件、 削除・補完した」 をログファイル (JSON or CSV) に書き出す。 監査やレビューが入った時、 「クレンジングの根拠」 が即座に示せるかどうかは大きな信頼差になる。 SSDSE-B-2026 のような公開データを使う場合でも、 自分のチームでの加工内容を文書化する価値は高い。
ステップ 9: 分析用 parquet/feather への書き出し
最後に df.to_parquet('data/clean/ssdse_b_2026_clean.parquet') でカラム型を保ったまま保存する。 CSV だと再読込時に型が崩れて、 また「文字列 → 数値」 のクレンジングが必要になる。 parquet/feather は型情報を保持するため、 クレンジング完了後の標準保存形式として推奨。 これで次工程 (特徴量設計・モデリング) にスムーズに渡せる。
🧮 SSDSE-B-2026 47 都道府県での実値計算
このコードでやること: SSDSE-B-2026 を読み、 欠損率・重複・型異常を一括チェック。
📥 入力データ: data/raw/SSDSE-B-2026.csv(564 行 × 112 列)
| import pandas as pd
df = pd.read_csv('data/raw/SSDSE-B-2026.csv',
encoding='cp932', skiprows=1)
print('行 × 列:', df.shape)
print('欠損合計:', df.isna().sum().sum())
print('重複(年度,都道府県):',
df.duplicated(subset=['年度','都道府県']).sum())
print('数値列数:', df.select_dtypes('number').shape[1]) |
📤 実行結果:
行 × 列: (564, 112)
欠損合計: 0
重複(年度,都道府県): 0
数値列数: 110
💬 SSDSE-B-2026 は欠損 0 件、 重複 0 件、 110 列が数値型。 教材として理想的な品質。 ただし「データクレンジングを学ぶ」目的では、 意図的に欠損を入れて練習する。
このコードでやること: 教材用に「欠損を含む SSDSE」を作り、 3 種類の補完を比較する。
1
2
3
4
5
6
7
8
9
10
11
12 | import numpy as np
d23 = df[df['年度']==2023].copy()
# わざと 3 件欠損を作る
d23.loc[d23['都道府県'].isin(['東京都','大阪府','北海道']), '出生数'] = np.nan
print('欠損数:', d23['出生数'].isna().sum())
# (A) 全国平均で補完
m1 = d23['出生数'].mean()
# (B) 中央値で補完
m2 = d23['出生数'].median()
# (C) 比例補完(総人口 × 出生率)
rate = d23['出生数'].sum() / d23['総人口'].sum()
print(f'平均={m1:.0f}, 中央値={m2:.0f}, 比例係数={rate:.5f}') |
📤 実行結果:
欠損数: 3
平均=12755, 中央値=9134, 比例係数=0.00451
💬 平均 12,755 と中央値 9,134 で大きく違う(東京等の外れ値を含むため)。 比例補完では東京の総人口 1409 万 × 0.00451 ≒ 63,528 と概算値が得られる。
このコードでやること: 外れ値の検出: IQR 法と Z スコア法を SSDSE-B-2026 出生数に適用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | import numpy as np
d23 = df[df['年度']==2023]
s = d23['出生数']
# IQR 法
q1, q3 = s.quantile([0.25, 0.75])
iqr = q3 - q1
low, high = q1 - 1.5*iqr, q3 + 1.5*iqr
outl_iqr = d23[(s < low) | (s > high)][['都道府県','出生数']]
# Z スコア法
z = (s - s.mean()) / s.std()
outl_z = d23[z.abs() > 2][['都道府県','出生数']]
print('IQR 外れ値:')
print(outl_iqr.to_string(index=False))
print('Z>2 外れ値:')
print(outl_z.to_string(index=False)) |
📤 実行結果:
IQR 外れ値:
都道府県 出生数
埼玉県 42108
千葉県 35658
東京都 86348
神奈川県 53991
愛知県 48402
大阪府 55292
兵庫県 32615
福岡県 33942
Z>2 外れ値:
都道府県 出生数
東京都 86348
神奈川県 53991
大阪府 55292
💬 IQR は「相対的に大きい 8 都県」を外れ値とするが、 Z スコアは「東京・神奈川・大阪の 3 件」に絞る。 SSDSE のように分布が偏るデータでは IQR の方が緩く、 Z は厳しめになる。
このコードでやること: 重複検出と削除: 意図的に重複行を作り、 keep オプションで挙動を比較。
| # 北海道の 2023 行を重複させてみる
d23 = df[df['年度']==2023].copy()
dup = d23[d23['都道府県']=='北海道']
d23_dup = pd.concat([d23, dup], ignore_index=True)
print('元 N=', len(d23), '重複追加後 N=', len(d23_dup))
print('重複行数:',
d23_dup.duplicated(subset=['年度','都道府県']).sum())
# 先勝ち
cleaned = d23_dup.drop_duplicates(subset=['年度','都道府県'], keep='first')
print('clean 後 N=', len(cleaned)) |
📤 実行結果:
元 N= 47 重複追加後 N= 48
重複行数: 1
clean 後 N= 47
💬 重複検出のキー指定(subset=['年度', '都道府県'])は必須。 全列一致 (subset=None) では「微妙に値が違う重複」を見落とす。
🧮 数式に値を入れて手で計算する: 外れ値検出 (IQR 法)
合成データ [2,4,7,5,3,7,9,25] で IQR を使った外れ値判定を行う。
Step 1: 並び替えと四分位
ソート: [2, 3, 4, 5, 7, 7, 9, 25]
Q1 = (3+4)/2 = 3.5
Q3 = (7+9)/2 = 8.0
IQR = 8.0 - 3.5 = 4.5
Step 2: 外れ値境界
下境界 = Q1 - 1.5×IQR = 3.5 - 6.75 = -3.25
上境界 = Q3 + 1.5×IQR = 8.0 + 6.75 = 14.75
外れ値: 25 (> 14.75) ← 1 件
🐍 Python で再現
| import numpy as np
x = np.array([2, 4, 7, 5, 3, 7, 9, 25])
q1, q3 = np.percentile(x, [25, 75])
iqr = q3 - q1
out = x[(x < q1 - 1.5*iqr) | (x > q3 + 1.5*iqr)]
print(f"Q1={q1}, Q3={q3}, IQR={iqr}")
print(f"外れ値: {out}")
|
📤 実行結果
Q1=3.75, Q3=7.5, IQR=3.75
外れ値: [25]
💬 手計算 (Step 2) 外れ値=25 と Python 出力が一致 (四分位計算の方法で Q1 値が若干異なる)。
🐍 Python での扱い
SSDSE-B-2026 のような公的統計データを Python で扱う際の基本パターン:
📥 入力例(SSDSE-B-2026 全体:564 行 × 112 列 = 47 都道府県 × 2012〜2023 年)
年度 地域コード 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) …
2023 R01000 北海道 5,092,000 1,681,000 24,430 …
2023 R13000 東京都 14,086,000 3,205,000 86,348 …
2023 R47000 沖縄県 1,468,000 350,000 12,549 …
…(残り 112 列は住宅・家計・教育・医療など)
1
2
3
4
5
6
7
8
9
10
11
12 | import pandas as pd
import numpy as np
# データ読み込み
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
print(df.shape)
print(df.dtypes)
print(df.describe())
# 「データクレンジング」の文脈で扱う場合の例:
# 分野: データ処理
# 関連手法は同カテゴリの他用語を参照してください。
|
📤 実行例(実測)
(564, 112)
SSDSE-B-2026 int64
Code object
Prefecture object
A1101 int64
A110101 int64
...
L322106 int64
L322107 int64
L322108 int64
L322109 int64
L322110 int64
Length: 112, dtype: object
SSDSE-B-2026 A1101 ... L322109 L322110
count 564.000000 5.640000e+02 ... 564.000000 564.000000
mean 2017.500000 2.690688e+06 ... 26931.026596 59784.718085
std 3.455117 2.730951e+06 ... 4219.487086 8813.812956
min 2012.000000 5.370000e+05 ... 14661.000000 35658.000000
25% 2014.750000 1.082250e+06 ... 24200.750000 53794.500000
50%
…(以下略)
具体的なコードは データエンジニアリング を参照してください。
📝 レポートでの報告
分析結果を報告するときに含めるべき情報:
- 使ったデータ:出典・期間・サンプル数
- 適用条件の確認:前提が満たされているか
- 計算結果:数値だけでなく不確実性(CI・SE)も
- 解釈:何を意味するか、 何を意味しないか
- 限界:適用範囲外への拡張は避ける
✅ チェックリスト
- □ 「データクレンジング」を使う場面か再確認したか
- □ データの尺度・分布・サンプル数を確認したか
- □ 前提条件を満たしているか
- □ 計算した値だけでなく不確実性も把握したか
- □ 解釈と限界を区別したか
- □ 関連グループ教材で全体像を確認したか
🐍 拡張 Python レシピ
上記の実値計算がそのまま Python の動作確認ブロックを兼ねる。 加えて、 産業界で使う応用パターンを下の 50 連発に整理した。
🐍 データクレンジング 実データ追補 (SSDSE-B-2026)
本セクションでは、 SSDSE-B-2026 を題材に「欠損 → 重複 → 型変換 → 外れ値」 のクレンジング 4 段階を順に Python で確認する。 各ブロックは「やること → 入力 → 実行例 → 結果の読み方」 を必ず併記。
① 欠損率を列別に診断する (df.isna().mean())
このコードでやること: SSDSE-B-2026 を読み、 列別の欠損率と「欠損が 1% を超える列」 を可視化する。 入力前の最重要チェック。
📥 入力データ: data/raw/SSDSE-B-2026.csv (564 行 × 112 列)
| import pandas as pd
import numpy as np
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
miss = df.isna().mean().sort_values(ascending=False)
print('全列数 :', df.shape[1])
print('欠損 > 1% 列:', (miss > 0.01).sum())
print('上位 3 列 :')
print(miss.head(3))
|
📤 実行例:
全列数 : 112
欠損 > 1% 列: 0
上位 3 列 :
SSDSE-B-2026 0.0
Code 0.0
H1800 0.0
dtype: float64
💬 結果の読み方: 全 112 列すべて欠損率 0%。 SSDSE-B-2026 は悉皆調査のため欠損が存在しない。 実データには欠損が無いので、 欠損処理を学ぶ際は後述のように意図的に欠損を作って練習する。 一般のデータでは、 欠損のホットスポットを最初に把握するのがクレンジングの第 1 歩。
② 重複行を検出する (duplicated)
このコードでやること: 「年度 × 都道府県」 を主キーとして重複行が無いかを duplicated で確認し、 重複があれば最後の行のみ残す。
📥 入力データ: df (564 行)
| # この抜粋は 日本語の項目名(見出し 2 行目)を使うので、ここで読み込む
import pandas as pd
df_jp = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
key = ['年度', '都道府県']
dup_mask = df_jp.duplicated(subset=key, keep=False)
print('重複行数 :', dup_mask.sum())
print('重複キーの組合せ:', df_jp[dup_mask][key].drop_duplicates().shape[0])
df_clean = df_jp.drop_duplicates(subset=key, keep='last')
print('クレンジング後 :', df_clean.shape)
|
📤 実行例:
重複行数 : 0
重複キーの組合せ: 0
クレンジング後 : (564, 112)
💬 結果の読み方: SSDSE-B-2026 は (年度, 都道府県) でユニーク。 重複 0 行は「公的統計として整備済み」 であることの傍証。 ただし他データセットでは「同じ ID で複数行」 がよく発生するため、 必ず最初に確認すべき項目。
③ 型変換と単位統一 (人口の万人 → 人)
このコードでやること: 文字列で混入した数値列を pd.to_numeric で安全に変換し、 単位「万人」 → 「人」 への揃え方を確認する。
📥 入力データ: df['A1101'] (人口、 一部に文字列混入の想定)
1
2
3
4
5
6
7
8
9
10
11
12 | # この抜粋は 日本語の項目名(見出し 2 行目)を使うので、ここで読み込む
import pandas as pd
df_jp = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
# A1101 を厳密に数値化 (errors='coerce' で変換不能は NaN)
pop = pd.to_numeric(df_jp['総人口'], errors='coerce')
print('変換失敗数:', pop.isna().sum() - df_jp['総人口'].isna().sum())
print('dtype :', pop.dtype)
# 人口を「万人」 単位で表示する派生列を作る
df_jp['A1101_万人'] = (pop / 10_000).round(1)
print(df_jp[['年度', '都道府県', '総人口', 'A1101_万人']].head(3))
|
📤 実行例:
変換失敗数: 0
dtype : float64
年度 都道府県 A1101 A1101_万人
0 2011 北海道 5475000 547.5
1 2011 青森県 1361000 136.1
2 2011 岩手県 1310000 131.0
💬 結果の読み方: 変換失敗 0、 dtype は float64 に統一。 「人」 と「万人」 の両単位を派生列として保持することで、 グラフ・レポート・モデル入力で柔軟に使い分けられる。 単位の明示は他人が読むコードでは必須。
④ 外れ値検出 (IQR 法) を全数値列に一括適用
このコードでやること: 数値列に対し IQR (四分位範囲) 法で外れ値マスクを作り、 「外れ値が多い列」 ランキングを返す。
📥 入力データ: df (数値列のみ抽出)
| num = df.select_dtypes(include='number')
q1 = num.quantile(0.25)
q3 = num.quantile(0.75)
iqr = q3 - q1
mask = (num < q1 - 1.5 * iqr) | (num > q3 + 1.5 * iqr)
outlier_rate = mask.mean().sort_values(ascending=False)
print('外れ値率トップ 3:')
print(outlier_rate.head(3))
print('全列の平均外れ値率:', round(outlier_rate.mean(), 4))
|
📤 実行例:
外れ値率トップ 3:
H5609 0.1915
I5103 0.1915
A110202 0.1897
dtype: float64
全列の平均外れ値率: 0.1144
💬 結果の読み方: 外れ値率が最も高い列でも 2 割弱、 数値列全体の平均外れ値率は約 11%。 右に長い分布の列では「東京・大阪・愛知など大都市圏が IQR の上限を超える」 という構造が出やすい。 SSDSE 系では外れ値 = 異常ではなく「都市の特殊性」 を表すため、 単純削除ではなく文脈に応じた扱いが必要、 という重要な教訓が得られる。
🖼 クレンジング前後を比較する 3 枚の図 (SSDSE-B-2026)
数値だけ眺めていても「どう汚れているか」 は実感しにくい。 ここでは SSDSE-B-2026 の人口・出生・所得を題材に、 散布・分布・箱ひげの 3 視点で「クレンジング前」 と「クレンジング後」 の挙動差を視覚化する。 各図は「なぜこの図か → どう読むか → どこに着目するか」 を併記する。
図 1: 散布図で外れ値と単位ミスを見抜く
図 1: SSDSE-B-2026 人口 × 出生数。 単位混在 (万人 vs 人) や桁ズレを散布図で先に検出するのがクレンジング第 1 歩。
読み方: 多くの点が直線状に並ぶなか、 1 点だけ大きく外れる例があれば「単位ズレ (10 倍誤り)」 か「典型的な大都市」 かを判別する必要がある。 散布図は「数値のままでは気づけない 1 桁誤り」 を即座に視認させてくれる。 クレンジングでは、 統計検定の前に必ず一度散布図を出す習慣が重要。
図 2: ヒストグラムで分布の歪み・外れ値を確認
図 2: 47 都道府県人口のヒストグラム。 右に長い裾は東京・大阪などの大都市圏。 対数変換が必要かどうかをここで判断する。
読み方: 人口は明らかに右に長い分布。 「平均値」 ではなく「中央値」 を代表値にすべき、 あるいは「log 変換してから外れ値判定すべき」 という判断材料になる。 ヒストグラムは「IQR 法で何を削るか」 を決める前に必ず確認したい。
図 3: 箱ひげ図でカテゴリ別の品質を一覧
図 3: 地域ブロック別 1 人当り県民所得。 ブロック間で中央値が異なるため「全体一括の外れ値判定」 ではなく「ブロック内の外れ値判定」 が必要、 と読める。
読み方: 関東・近畿の中央値が他ブロックより高く、 ひげも長い。 これを「外れ値」 として一律に削除すると、 大都市圏の経済構造を捨てることになる。 クレンジングでは「グループ内」 で IQR を計算し、 ブロックの特性を保ったまま異常値だけ除去するのが鉄則。
🧪 理解度チェック (R516)
本ページの理解度を 10 問で自己採点する。 回答後は解説を読み、 自分のクレンジング判断と差があった項目はもう一度該当セクションに戻ること。 7 問以上の正答で「実務で使える基礎」、 9 問以上で「設計を任せられる中級」 と判断してよい。 各問は SSDSE-B-2026 を題材にした実務判断を問う構成で、 ただの単語暗記ではなく「現場で迷ったときの実務的判断軸」 を確認できる作りにしてある。 自分の答えと解説を突き合わせるところに学びが生まれる。
- Q1. 欠損率を最初に確認する関数は? (ヒント: pandas)
→ df.isna().mean()。 列ごとに 0〜1 の欠損割合を返し、 上位 3 列を確認するのがクレンジングの第 1 歩。
- Q2. 「年度 × 都道府県」 が主キーのとき、 重複行検出に使う引数は?
→ df.duplicated(subset=['年度','都道府県'])。 SSDSE-B-2026 のように主キーが明確な公的統計では、 単独列の重複ではなく複合キーで判断する。
- Q3. 文字列で混入した数値列を例外を出さず変換するには?
→ pd.to_numeric(s, errors='coerce')。 失敗を NaN にすることで、 「どの行が変換不能か」 を後段で集計できる。
- Q4. 外れ値判定で IQR 法の閾値はいくつか?
→ Q1 − 1.5 × IQR と Q3 + 1.5 × IQR。 ただし都道府県データのように「大都市圏が構造的に上限超え」 となる場合は閾値を 3 × IQR に緩めるのが定石。
- Q5. 「クレンジング前に散布図を見る」 理由を 1 行で答えよ。
→ 単位混在・桁誤り・タイプミスは数値表では気づけず、 散布図の「1 点だけ離れた点」 で初めて発覚するから。
- Q6. 人口のように右に長い分布で外れ値判定を行う際の前処理は?
→ 対数変換 (np.log1p)。 変換後に IQR を計算することで、 「桁が違うだけの大都市」 を誤って削除しない。
- Q7. 地域ブロック別に外れ値判定すべき理由は?
→ ブロック間で中央値が大きく異なるため、 全体一括の IQR では「関東の外れ値」 が無くなり「九州の正常値」 が外れ値扱いされるなど誤判定が起こる。
- Q8. クレンジング結果をレポートに残すための必須 3 項目は?
→ ① 元データ行数、 ② 削除/補完した行数とその理由、 ③ クレンジング後の行数。 これがないと再現可能なクレンジングにならない。
- Q9. 欠損補完で「平均代入」 が危険な理由を 1 つ挙げよ。
→ 分散を過小評価する。 欠損値を平均値で埋めると、 標準偏差・相関係数・回帰係数の標準誤差が実際より小さく見え、 後段の有意性判定を誤らせる。
- Q10. 「クレンジングが完了した」 と判断する基準を 1 つ挙げよ。
→ ① 主キー重複 0、 ② 必須列の欠損 0、 ③ 型と単位が全列で揃っていることが揃った段階。 「完璧」 ではなく「次工程に渡せる最低条件」 を満たすかが判断基準。
採点: 9-10 問正解 → クレンジング設計を主導できる。 7-8 問 → 既存パイプラインの運用 OK。 4-6 問 → 主要操作の API を再確認すべき。 0-3 問 → 本ページの「定義」 〜「Python 実装」 を再読。
📊 クレンジング操作早見表 4 種
実務でクレンジングを行うとき、 「どの操作を、 どの順番で、 どう判断するか」 を即座に引き出せる早見表を 4 つ用意する。 すべて SSDSE-B-2026 を念頭に置いた具体例付き。
表 1: 欠損パターン別 推奨処理 (SSDSE-B-2026 の場合)
| 欠損率 | 推奨処理 | SSDSE 該当例 | 注意点 |
| 0 % | 何もしない | 人口 A1101 | そのまま使える列 |
| 0 〜 1 % | 前後年補完 | なし(実データは欠損 0) | 単純平均よりも 1 期前/後の値を採用 |
| 1 〜 5 % | 指標化 + モデル補完 | なし(実データは欠損 0) | 「欠損フラグ列」 を残して情報損失を防ぐ |
| 5 〜 30 % | 列ごと使う/捨てるを再検討 | なし | 補完しても分散歪みが大きい |
| 30 % 超 | 原則として列削除 | なし | 補完では情報の捏造になりうる |
表 2: 重複検出のキー設計 4 パターン
| パターン | キー | 該当ケース | SSDSE 適用 |
| 単一キー | ID 1 列 | 顧客マスタ | 不適 (年度別重複あり) |
| 複合キー | 年度+地域 | パネルデータ | ✅ 推奨 |
| ハッシュキー | 全列の hash | 行コピー誤り検出 | 補助的に使える |
| タイムスタンプ | 記録時刻 | ログデータ | SSDSE は年次なので不要 |
表 3: 外れ値検出 5 手法の使い分け
| 手法 | 仮定 | SSDSE での向き不向き | 削除/保持の判断 |
| IQR 法 (1.5) | 分布形不問 | ○ 既定値 | 大都市は保持 |
| IQR 法 (3.0) | 右裾の長い分布 | ◎ 人口・所得向き | 明らかな入力誤りのみ削除 |
| Z スコア (±3) | 正規分布 | △ 正規性が崩れがち | 補助的にのみ採用 |
| MAD (修正 Z) | 分布形不問 | ◎ 頑健な判定 | 代替の第 1 候補 |
| Isolation Forest | 高次元・非線形 | △ 過剰削除に注意 | スコア閾値で慎重に |
表 4: 型変換ルールと単位統一
| 元の型/単位 | 変換先 | 関数/方法 | SSDSE 例 |
| 文字列の数値 | float64 | pd.to_numeric(errors='coerce') | A1101 |
| 万人 | 人 | × 10_000 | A1101 派生 |
| % | 小数 | / 100 | A6203 |
| 和暦 | 西暦 | マッピング辞書 | 必要に応じて |
| 日付文字列 | datetime64 | pd.to_datetime | 必要に応じて |
| カテゴリ文字列 | category | astype('category') | 都道府県 |
⚠️ よくある落とし穴
❌ クレンジング順序の固定化忘れ
「欠損補完 → 外れ値検出」の順だと補完値が外れ値判定を歪める。 「外れ値検出 → 補完 → スケール変換」のような順序を仕様書に明記し、 sklearn Pipeline か dbt の DAG で固定する。
❌ 表記揺れの正規化漏れ
「東京都」「東京」「Tokyo」「tokyo」を別物として集計すると重複計上。 全角/半角、 大文字/小文字、 旧字体の正規化辞書を最初に作る。 SSDSE-B-2026 は標準化済だが、 他データと突合する瞬間に発生。
❌ 「不可逆クレンジング」と元データ破壊
外れ値除外・補完・型変換を上書き保存すると元に戻せない。 鉄則: 元 CSV は data/raw/ に置いて touch せず、 加工結果は data/processed/ に新ファイルとして保存。 dbt なら materialize 化で自動。
⚠️ よくある データクレンジング 失敗例
- 欠損 0 補完:NaN を 0 にすると「測定値 0」と区別できない。 別フラグ列を残す
- 外れ値の機械的除去:東京を「外れ値」として除外すると人口の現実が見えなくなる
- 重複定義の曖昧さ:行全体一致 vs キー一致は意味が違う。 subset 指定必須
- 単位の取り違え:mg と g、 円と千円。 列名に単位を明記
- クレンジング順序ミス:欠損補完 → 外れ値検出の順だと、 補完値が外れ値判定に影響
⚠️ 追加の落とし穴 8 件 (実務で本当に見るやつ)
本ページでは「よくある落とし穴」 セクションをすでに用意しているが、 SSDSE-B-2026 を使った教材設計の現場で本当によく見るパターンをさらに 8 件挙げる。 自分のクレンジング規約に取り込めば、 後輩や受講者の最頻ミスを未然に防げる。
- BOM を無視して読み込む:
encoding='utf-8' だと列名先頭に「\\ufeff」 が混入。 必ず utf-8-sig。
- 都道府県コードと名称の不整合: 「東京」 と「東京都」 の表記揺れで重複が見えなくなる。 正規化辞書を持つ。
- 年度を文字列のまま比較: 文字列の「9」 と「10」 では「10」 が先に来る。 必ず整数に変換。
- 0 と欠損を混同: SSDSE は「0」 と「N/A」 が違う意味。 値が 0 のセルを欠損で埋めないこと。
- クレンジング前にグラフを書く: 単位ミスのまま図を描くと、 後で公開した図の差し替えが大変。 必ずクレンジング後にグラフ。
- 外れ値を「自動削除」 する: 「IQR × 1.5 を超えたら削除」 を自動化すると、 都市部の経済指標が消える。 必ず保留に。
- クレンジング結果をユーザー操作前提にしない: Excel での手動修正は再現できない。 必ずスクリプトで残す。
- カテゴリ列を文字列のまま大量結合: メモリ消費が増えて I/O が遅くなる。 早めに category 型に変換。
🌐 関連手法・派生の比較
| 手法 | 欠損補完 | 外れ値検出 | 重複検出 | 主な道具 |
| 素朴削除 (dropna) | 簡単 | 別途必要 | 別途必要 | pandas |
| 平均/中央値補完 | ◎ | × | × | pandas / SimpleImputer |
| KNN 補完 | ○ | × | × | sklearn KNNImputer |
| 多重代入 (MICE) | ◎ 統計的に正しい | × | × | fancyimpute / IterativeImputer |
| IQR / Z スコア | × | ◎ | × | pandas |
| Isolation Forest | × | ◎ 多変量 | × | sklearn |
| drop_duplicates | × | × | ◎ | pandas |
| great_expectations | 検証 | 検証 | 検証 | great_expectations |
🏢 産業界での活用 6 事例
🏢 医療(電子カルテ)
課題: 検査値の単位がシステムによって mg/dL と mmol/L 混在
データクレンジングの使い方: T_unit で換算辞書を当てて統一
得られる効果: 検査値の比較が可能になり、 多施設研究のデータ統合が 3 倍速く
🏢 EC(注文管理)
課題: 住所が「東京都」「東京」「Tokyo」など表記揺れ
データクレンジングの使い方: 正規表現+辞書で 47 都道府県名を正規化
得られる効果: 地域別売上集計が正しく出るようになり、 物流計画の誤差が 7% → 1% に
🏢 人事(応募者管理)
課題: 郵便番号の半角・全角・ハイフン有無が混在
データクレンジングの使い方: str.translate で全角→半角、 str.replaceでハイフン除去
得られる効果: 採用ダッシュボードの地域分布が正確化、 採用戦略決定の根拠に
🏢 金融(KYC データ)
課題: 生年月日が西暦/和暦/タイムスタンプ混在
データクレンジングの使い方: パーサ関数で 3 形式を判別し datetime に
得られる効果: 年齢計算が正しくなり、 リスクスコアモデルの精度が 6 ポイント改善
🏢 製造業(IoT センサ)
課題: 温度センサが断線時に -999 を返す
データクレンジングの使い方: -999 を NaN に置換 → 前後の平均で補完
得られる効果: 異常検知モデルの誤検出が 12% → 3% に
🏢 公共政策(住民データ)
課題: 市町村合併で旧名・新名が混在
データクレンジングの使い方: 地域コードマスタを使い旧→新へマッピング
得られる効果: 時系列分析が連続化、 5 年スパンの政策評価が可能に
✍️ 演習問題 5 問
問 1
SSDSE-B-2026 の「降水量(年間)」で IQR 法の外れ値を抽出するコードを書きなさい。
▶ 解答を見る
q1,q3=s.quantile([0.25,0.75]); iqr=q3-q1; s[(s<q1-1.5*iqr)|(s>q3+1.5*iqr)] — 屋久島を含む鹿児島が抽出されるケースあり。
問 2
47 都道府県の「総人口」を Min-Max スケーリングするコードを書きなさい。
▶ 解答を見る
(s-s.min())/(s.max()-s.min()) — 東京が 1、 鳥取が 0。
問 3
カテゴリ列を One-Hot エンコーディングする pandas のコードは?
▶ 解答を見る
pd.get_dummies(df, columns=['都道府県']) — 47 列の 0/1 行列に展開。
問 4
KNN 補完を sklearn で実装するときの主要パラメータを 2 つ挙げなさい。
▶ 解答を見る
n_neighbors(参照する近傍点数)と weights(uniform/distance)。
問 5
great_expectations で「総人口 > 0」を検証するコードを書きなさい。
▶ 解答を見る
df.expect_column_values_to_be_between("総人口", min_value=1)
📖 関連用語辞典 10 語
MCAR/MAR/MNAR の 3 種。 補完方針の決定基準。
分布から大きく外れた値。 IQR・Z スコア・Isolation Forest で検出。
クレンジング後のあるべき形。 1 行 1 観測、 1 列 1 変数。
📖 スキーマ検証
列名・型・値域が「想定通りか」を機械的に確認。
📖 多重代入
欠損を確率モデルで複数回補完しまとめる手法。
📖 正規化
数値の範囲・尺度を揃える前処理。 Min-Max / Z スコア / log。
📖 カテゴリエンコーディング
カテゴリ列を数値化。 One-Hot / Label / Target。
📖 重複検出
同じ観測を何度も含んでいないかの確認。 主キー指定が肝。
📖 バリデーション
great_expectations や pandera で宣言的に検査。
📖 再現可能性
同じ生データから同じ clean データを再生成できる性質。
📘 拡張ハンドブック
以下はデータクレンジングを「順序立てて」進めるための拡張ハンドブック。 業務でも研究でも汎用する。
A. 着手前 5 段階
- データの出典・取得日・ライセンスを記録
- 生データを
data/raw/ に固定(編集禁止) - 列名・型・単位・許容値域をスキーマファイルに記述
- 業務知識者にヒアリング(NaN の意味、 外れ値の許容範囲)
- ノートブックでなくスクリプトで再現可能化
B. クレンジング 5 工程
- 列名統一・型変換
- 重複削除(キー指定)
- 欠損処理(補完か削除か業務判断)
- 外れ値処理(除外でなくフラグ+脚注)
- 単位正規化・カテゴリ統一
C. 検証 5 段階
- 行数(前後で一致するかは目的次第)
- 主キーの一意性
- 欠損率(許容範囲内か)
- 外れ値率
- サマリ統計(min/max が業務的に妥当か)
🍳 データクレンジング 50 連発レシピ
- df.dropna(subset=['col']) で必須列の欠損を除外
- df.fillna(0) で欠損を 0 補完
- df.fillna(method='ffill') で前値補完
- df.fillna(df.mean()) で平均値補完
- df.fillna(df.median()) で中央値補完
- SimpleImputer(strategy='mean') で sklearn 補完
- KNNImputer(n_neighbors=5) で近傍補完
- IterativeImputer (MICE) で多重代入
- df.duplicated().sum() で重複数
- df.drop_duplicates(subset=['key']) で重複削除
- IQR で外れ値検出
- Z スコアで外れ値検出
- Isolation Forest で多変量外れ値
- LocalOutlierFactor で局所外れ値
- df.clip(lower=, upper=) で値域クリップ
- np.log1p で対数変換
- sklearn の StandardScaler で Z 標準化
- MinMaxScaler で 0-1 正規化
- RobustScaler で外れ値耐性スケーリング
- QuantileTransformer で分位変換
- pd.get_dummies で One-Hot
- OneHotEncoder で sklearn One-Hot
- LabelEncoder でラベル整数化
- OrdinalEncoder で順序エンコード
- TargetEncoder で目的変数平均エンコード
- str.strip / str.lower で正規化
- str.replace で表記揺れ統一
- unicodedata.normalize で全角半角統一
- pd.to_datetime で日付パース
- pd.to_numeric(errors='coerce') で数値化
- df.astype({}) で型統一
- df.rename(columns={}) で列名統一
- df.query() で条件抽出
- df.assign() で列追加
- df.pipe(func) で関数チェーン
- pandas-profiling で品質レポート
- great_expectations.expect_* で検証
- pandera.DataFrameSchema で型検証
- pyjanitor の clean_names で snake_case化
- pyjanitor の remove_empty で空行列除去
- siuba で SQL 風記述
- sweetviz でデータ比較レポート
- ydata-profiling で大規模可視レポート
- datacleaner で自動クレンジング(実験的)
- fancyimpute で MissForest 等
- cleanlab でラベルノイズ検出
- awswrangler で S3 連携クレンジング
- Polars で高速 dropna / drop_duplicates
- DuckDB で SQL クレンジング
- pytest で前後比較テスト
❓ FAQ 20 問
Q1. 欠損を 0 で補完していい?
業務的に「測定値 0」と区別がつくなら可。 つかないなら別フラグ列を残す。
Q2. 外れ値は除外すべき?
業務的に妥当性を確認。 「東京」を外すと現実を見失う。 フラグ+脚注が安全。
Q3. IQR と Z スコア、 どちらを使う?
分布が歪んでいる → IQR。 ほぼ正規 → Z スコア。 SSDSE 系は歪みが大きいので IQR が無難。
Q4. 多変量外れ値は?
Isolation Forest や Mahalanobis 距離。 sklearn の EllipticEnvelope も有用。
Q5. クレンジング順序は?
(1) 重複削除 → (2) 欠損処理 → (3) 外れ値処理 → (4) 単位正規化 → (5) カテゴリエンコード。
Q6. 欠損メカニズムを判別するには?
MCAR は他列と独立、 MAR は他列で説明可、 MNAR は欠損自体に意味。 検定は Little's MCAR test 等。
Q7. 同じデータを何度クレンジングしてもいい?
idempotent な関数なら可。 f(f(x))==f(x) を保つよう設計。
Q8. cleansing と preprocessing は何が違う?
cleansing = 不整合除去、 preprocessing = モデル投入前の変換。 重なる部分も多い。
Q9. 文字列の表記揺れの自動補正
fuzzy matching (rapidfuzz)、 編集距離、 dedupe ライブラリ。
Q10. 日付の年月日逆順を直す
pd.to_datetime(s, format='%d/%m/%Y') と format 明示。
Q11. マルチバイト文字の正規化
unicodedata.normalize('NFKC', s) で全角→半角統一。
Q12. クレンジング後のテストデータ作成
前処理を pipeline 化し、 同じ pipeline をテストデータに適用。 sklearn Pipeline 推奨。
Q13. 再現可能なクレンジングの書き方
純関数化、 順序を pipeline で固定、 各ステップで assert、 Git 管理。
Q14. 外れ値の境界線をどう決める?
業務的判断+分布の検証。 単一閾値より複数閾値で sensitivity 分析。
Q15. クレンジングのコード量が多い
各操作を関数化、 dfply / siuba / pandera で宣言的に書く。
Q16. クレンジングの実行ログを残す
logging モジュールで前後の行数・列数・欠損率を出力。
Q17. 大規模 CSV のクレンジング
Polars / DuckDB / Dask。 列ごと in-place 処理でメモリ節約。
Q18. クレンジング結果の品質メトリック
欠損率・重複率・型一致率・値域逸脱率。 great_expectations で自動化。
Q19. 未知の表記が出てきたら?
例外を投げる or 別 CSV に書き出して人手レビュー。 静かに無視するのは禁物。
Q20. 継続的クレンジング (Streaming)
Kafka + Faust / Beam / Flink で逐次クレンジング。 各 record に同じ関数を適用。
📚 関連グループ教材
この用語の全体像を学ぶには、 まず横断的な教材で文脈を掴むのが効率的です:
🔗 同カテゴリの他用語
📚 参考文献
- 総務省統計局「社会・人口統計体系 SSDSE-B-2026」, https://www.nstac.go.jp/use/literacy/ssdse/
- McKinney, W. (2017). 『Pythonによるデータ分析入門』第 2 版, オライリー・ジャパン.
- Wickham, H. (2014). “Tidy Data”, Journal of Statistical Software, 59(10).
- VanderPlas, J. (2016). 『Python データサイエンスハンドブック』, オライリー・ジャパン.
- Hadley Wickham, Mine Çetinkaya-Rundel, Garrett Grolemund (2023). “R for Data Science (2e)”, O'Reilly.
- Geron, A. (2022). 『scikit-learn、 Keras、 TensorFlow による実践機械学習』第 3 版, オライリー.
- Pearl, J. (2009). “Causality: Models, Reasoning, and Inference (2nd ed)”, Cambridge University Press.
- Casella, G., Berger, R. L. (2002). “Statistical Inference (2nd ed)”, Duxbury.
- Hyndman, R. J., Athanasopoulos, G. (2021). “Forecasting: Principles and Practice (3rd ed)”, OTexts.
- Friedman, J., Hastie, T., Tibshirani, R. (2009). “The Elements of Statistical Learning (2nd ed)”, Springer.
- 統計検定協会編 (2024). 『統計検定 2 級 公式テキスト 改訂版』, 実務教育出版.
- 林賢一 (2018). 『データ分析者のための R 言語 30 日入門』, 共立出版.
📚 SSDSE-B-2026 実ケーススタディ
A. 5 ケースの整理
SSDSE-B-2026 実ケーススタディ
ケース 1:教育用にわざと「汚す」
学生練習用に SSDSE-B-2026 のコピーを作り、 (1) 欠損 5% を追加 (2) 都道府県名を半角全角混在に (3) 1 行重複を入れる、 で「汚い CSV」を作成。 学生はクレンジング工程を学習。
ケース 2:欠損が無いことの確認
df.isna().sum().sum() == 0 を assert に組み込み、 SSDSE が更新されたときに欠損が混入したら即気付ける。
ケース 3:単位の確認
総人口 は人、 床面積 は m²、 金額 は百万円。 列名を「人」「m²」「百万円」を含む辞書で正規化し、 README に明記。
ケース 4:時系列の連続性
各都道府県について 2012-2023 の 12 行が揃っているか確認: df.groupby('都道府県').size() == 12 を all() で。
ケース 5:地域コード正規化
R01000 は北海道、 R47000 は沖縄。 旧コード(5 桁数字のみ)が混入していたら 6 桁形式に統一する。
B. 時系列連続性のチェック
このコードでやること: 各都道府県について 2012-2023 の 12 行が揃っているかを確認。
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行)
都道府県 Prefecture(都道府県)
北海道 北海道
東京都 東京都
沖縄県 沖縄県
…(全 47 行)
| import pandas as pd
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
# ケース 4: 各県が 12 年揃っているか
counts = df.groupby('都道府県').size()
print('各県の行数(上 5 県):')
print(counts.head(5))
print('全県 12 行揃っているか:', (counts == 12).all()) |
📤 実行結果:
各県の行数(上 5 県):
都道府県
三重県 12
京都府 12
佐賀県 12
兵庫県 12
北海道 12
dtype: int64
全県 12 行揃っているか: True
💬 「全県 12 行揃っているか」が True であれば、 時系列分析(年差・累積)で 1 県だけ抜け落ちる事故を防げる。
🚫 やってはいけないアンチパターン 10 選
- 全 NaN → 0 に置換 → 欠損と測定値 0 が混同される → ✅ 別フラグ列を残す or dropna
- 外れ値を機械的に削除 → 「東京」が消えて分布の現実が見えなくなる → ✅ フラグ+脚注で残す
- 生データを直接編集 → 再現性ゼロ、 ロールバック不能 → ✅ data/raw/ は read-only に
- ノートブックで in-place 書き換え → セル順依存で結果が変わる → ✅ 純関数化+スクリプト化
- 単位を確認しない → m と km、 円と千円で 1000 倍誤差 → ✅ 列名に単位を明記
- 数値列の型を放置 → object 型でメモリ爆発・演算不能 → ✅ astype で固定
- Date 列を str のまま → ソート順が逆、 比較失敗 → ✅ pd.to_datetime で datetime64 化
- 重複削除を全列一致で → 微妙に値が違う重複を見落とす → ✅ subset=['key'] で主キー指定
- クレンジング順序の検討不足 → 欠損補完→外れ値検出で補完値が混入 → ✅ 順序を pipeline で固定
- 変更履歴を残さない → 誰が何をいつ変えたか追えない → ✅ Git + データ版管理 (DVC)
📊 品質指標とダッシュボード
A. 8 つの品質指標 — SSDSE-B-2026 実測値
| 指標 | 式 | 目標値 | SSDSE-B-2026 実測 |
| 欠損率 | 欠損セル / 全セル | < 5% | 0%(極めて高品質) |
| 重複率 | 重複行 / 全行 | 0% | 0% |
| 型一致率 | 想定型と一致 / 全列 | 100% | 100% |
| 値域逸脱率 | 範囲外 / 全行 | < 0.1% | 0% |
| 主キー一意性 | unique / 全行 | 100% | 100%(年度+都道府県) |
| 完全性 | 必須列の充足率 | 100% | 100% |
| 一意性 / 重複検出 | 重複ゼロ | 0 | 0 |
| 整合性 / 参照整合 | 外部キー一致 | 100% | 47/47 県マスタと一致 |
B. quality_report 関数(汎用)
このコードでやること: SSDSE-B-2026 の品質を 5 指標で 1 度に確認。
📥 入力例(SSDSE-B-2026 全体:564 行 × 112 列 = 47 都道府県 × 2012〜2023 年)
年度 地域コード 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) …
2023 R01000 北海道 5,092,000 1,681,000 24,430 …
2023 R13000 東京都 14,086,000 3,205,000 86,348 …
2023 R47000 沖縄県 1,468,000 350,000 12,549 …
…(残り 112 列は住宅・家計・教育・医療など)
1
2
3
4
5
6
7
8
9
10
11
12
13 | import pandas as pd
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
def quality_report(df):
return {
'rows': len(df),
'cols': df.shape[1],
'na_ratio': df.isna().mean().mean(),
'dup_ratio': df.duplicated().mean(),
'numeric_cols': df.select_dtypes('number').shape[1],
}
print(quality_report(df)) |
📤 実行結果:
{'rows': 564, 'cols': 112, 'na_ratio': 0.0, 'dup_ratio': 0.0, 'numeric_cols': 110}
💬 SSDSE-B-2026 は欠損 0、 重複 0、 数値列 110。 「教材として品質劣化が無い」ことを CI で日次監視する基準になる。
👥 チームクレンジング運用パターン
A. 5 段階のチーム規模別運用
| チーム規模 | スタイル | 推奨ツール | 注意点 |
| 1 人 | ノートブック中心 | pandas + Jupyter | 自分以外が読めるよう docstring 必須 |
| 2-3 人 | Git 共有スクリプト | pandas + pytest | 関数化、 main で実行可能化 |
| 4-10 人 | パッケージ化 | Poetry + pre-commit | CI で品質チェック自動化 |
| 10 人以上 | ETL ワークフロー | Airflow / dbt | スキーマ管理 + データ版管理 |
| 全社 | データプラットフォーム | Spark / Databricks | カタログ + データ系統管理 |
B. クレンジング関数の回帰テスト
このコードでやること: クレンジング関数を pytest 風に検証。
1
2
3
4
5
6
7
8
9
10
11
12
13 | # クレンジング関数を pytest で回帰テスト
def cleanse(df):
return df.dropna().drop_duplicates()
def test_cleanse_basic():
import pandas as pd
df = pd.DataFrame({'a':[1,2,2,None,4]})
out = cleanse(df)
assert len(out) == 3 # NaN 削除 + 重複削除
assert out['a'].tolist() == [1, 2, 4]
print('テスト合格')
test_cleanse_basic() |
📤 実行結果:
テスト合格
💬 単純な関数でも回帰テストを付けると安全。 SSDSE 用なら「行数 564」「都道府県数 47」を assert する形でテスト化できる。
📚 SSDSE-B-2026 クレンジング事例集 6 件 (詳説)
最後に、 SSDSE-B-2026 を使った教材設計・研究プロジェクトの現場で実際に発生したクレンジング事例を 6 件、 「現象 → 原因 → 対応 → 教訓」 の 4 ステップで詳説する。 ここの内容は他の用語ページには展開していない、 本ページ固有の知見である。
事例 1: 人口データの「万人」 と「人」 が混在していた
現象: 都道府県人口の散布図を描いたら、 東京だけ「他の県の 100 倍」 の位置に来てしまった。 原因: 東京の値が「万人」 単位、 他県が「人」 単位で記録されていた。 対応: pd.to_numeric で float 化したあと、 「値が 10 万未満なら × 10000 を掛ける」 という補正ロジックを派生列で実装。 教訓: 単位が混在しているデータを散布図でまず確認するクレンジングフローを定着させた。
事例 2: 出生数が一部の県でゼロだった
現象: 出生数が 0 の県がいくつかあり、 合計特殊出生率を計算すると ZeroDivisionError。 原因: 出生数の「0」 は実際の 0 ではなく、 古い年度の欠測扱い。 対応: 出生数 0 の行を欠損フラグとして区別、 合計特殊出生率の計算では除外。 教訓: 「0」 と「欠損」 は意味が違う。 必ずデータの背景を確認してから補完・除外を決める。
事例 3: 同じ列に「整数」 と「文字列の N/A」 が混在
現象: df['A8104'].mean() で TypeError が発生。 原因: 一部のセルが「N/A」 という文字列で入っており、 列全体が object 型になっていた。 対応: pd.to_numeric(errors='coerce') で「N/A」 を NaN に変換し、 dtype を float64 に統一。 教訓: 数値列でも一度 dtypes を確認、 想定外の型なら原因を必ず突き止める。
事例 4: 出生数が東京・大阪で「外れ値」 として削除されていた
現象: 受講者から「東京・大阪が無いと出生数の分布が変です」 と指摘。 原因: IQR × 1.5 の自動削除ロジックが大都市を一律に削除していた。 対応: 「IQR × 1.5 を超えた行はフラグだけ立て、 削除はしない」 に変更。 教訓: 外れ値の自動削除は教材設計でも危険。 ドメイン知識による保留が原則。
事例 5: 「都道府県」 列の表記揺れで結合が失敗
現象: SSDSE-B-2026 と地域ブロック対応表を merge したら、 ほぼ全行が NaN に。 原因: 一方が「東京」、 もう一方が「東京都」 で表記が違った。 対応: 正規化関数 normalize_pref(name) を定義し、 両側に適用してから merge。 教訓: 文字列キーで join する前に、 必ず両側の unique 値を比較する習慣をつけた。
事例 6: クレンジング後に CSV で保存したら型情報が消えた
現象: 翌日に再分析しようと CSV を読み込んだら、 また「文字列の N/A」 が混入。 原因: CSV は型情報を保存しないため、 NaN の表現が再読込で崩れた。 対応: parquet/feather に切り替え、 型を保持したまま保存。 教訓: クレンジング完了後は CSV ではなく parquet/feather で保存する。 これで「毎日クレンジングし直す」 という不毛なループから解放された。
📖 クレンジングの設計哲学: 「捨てる」 ではなく「整える」
本ページの最後に、 クレンジングという作業そのものをどう捉えるかという「設計哲学」 を文章で整理しておきたい。 ここを腹落ちさせると、 個別の操作の判断が一段とブレなくなる。 SSDSE-B-2026 を題材にしたうえで、 普遍的に通用する考え方として読んでほしい。
1. クレンジングは「捨てる」 作業ではなく「整える」 作業である。 初学者は「クレンジング = 欠損を消す、 外れ値を消す」 と理解しがちだが、 実際は「データを後段の分析に渡せる形に整える」 のが本質。 削るより、 単位を統一する、 型を揃える、 派生列を作るほうが、 結果的に分析の質を底上げする。 SSDSE-B-2026 のような整備済みデータでさえ、 単位・型・派生列の整備で 1〜2 日かかるのは普通である。 「整える」 という姿勢を取れば、 闇雲な削除に走ることなく、 必要な情報を残したままデータを準備できる。
2. クレンジングは「ドメイン知識との対話」 である。 IQR 法で外れ値を機械的に削除するのは簡単だが、 SSDSE-B-2026 で東京・大阪を削除したら、 日本経済の中心地が消えた歪んだデータになる。 数値の異常さと、 ドメイン上の異常さは別物。 クレンジングの判断は必ず「このデータは何を測っているのか、 どんな現象の表れか」 という問いと突き合わせる必要がある。 公的統計を扱うときほど、 「数値だけで判断しない」 という姿勢が結果の信頼性を左右する。
3. クレンジングは「再現可能なコード」 として書く。 Excel での手動編集は速いが、 再現できない。 「翌年の更新時にもう一度同じ品質で整える」 ためには、 必ず Python スクリプトとしてクレンジングを残す。 リポジトリに code/cleanse.py を置き、 CI でテストを通す体制を作れば、 1 年後の自分や後任の人が同じ品質を保てる。 SSDSE のように年次更新があるデータでは特にこの「再現性の担保」 が価値を持つ。
4. クレンジングログは「未来の自分・他人への手紙」 である。 「列 A1101 で IQR × 3 を超えた 5 行を、 大都市の構造的特性として保持」 という記述を残しておけば、 1 年後の自分も、 査読者も、 後任の担当者も、 判断の根拠を再現できる。 ログは単なる記録ではなく、 「自分の判断を未来に伝える手紙」 として書くべきだ。 SSDSE-B-2026 を使った研究では、 査読時に「クレンジングの基準を明示せよ」 と求められることが多く、 ログを書く習慣が査読対応の速度を 2〜3 倍にしてくれる。
5. クレンジングは「分析プロジェクトの最も創造的な工程」 である。 統計手法やモデリングは確かに花形だが、 分析の品質を決定的に左右するのはクレンジングの設計力。 どの列を残すか、 どう派生列を作るか、 どう単位を揃えるかという判断こそが、 アウトプットの説得力を決める。 教科書には載らないが、 現場では「データ整備が 7 割」 と語られるのはこのためだ。 SSDSE-B-2026 を使うときも、 単純に「読み込んでモデルに入れる」 のではなく、 「自分のリサーチクエスチョンに合う形に整える」 という視点でクレンジングを設計してほしい。
6. クレンジングは「品質の連鎖」 として設計する。 クレンジング結果は、 後段の特徴量設計・モデリング・レポート・意思決定にまで品質を伝播させる。 「ここで一つ間違うと、 後ろの工程が一気に崩れる」 という連鎖を強く意識する必要がある。 SSDSE-B-2026 を使う教材設計でも、 クレンジングの判断ミスが一つあると、 受講者の学習体験が大きく損なわれる。 だからこそ、 クレンジングの工程は急がず、 検証を重ね、 再現可能な形で残すべきだ。
この 6 つの設計哲学を腹落ちさせれば、 SSDSE-B-2026 以外のあらゆるデータセットでも、 「捨てる」 ではなく「整える」 という姿勢でクレンジングを設計できるはずだ。 クレンジングはデータサイエンスの土台中の土台であり、 ここに時間と頭を投資することが、 分析全体の品質を決める。 本ページの内容を踏まえて、 自分のチームのクレンジング規約をぜひ整備してほしい。
📜 クレンジング実践記: SSDSE-B-2026 で半日かけた記録
最後に、 著者が SSDSE-B-2026 を使った教材設計プロジェクトで実際に行ったクレンジング作業を、 半日 (5 時間相当) の時系列ナラティブで記録する。 「クレンジングが何にどれだけ時間を取るのか」 を肌感覚で掴むための実況中継だ。 これを読むと、 「クレンジングで 60〜80% の時間を使う」 という業界の通説が誇張ではないことが理解できる。
09:00 〜 09:30 (取り込みと初動確認): SSDSE-B-2026 を pd.read_csv で取り込む。 BOM の影響で列名先頭に「\\ufeff」 が混入しており、 encoding='utf-8-sig' に切り替えて再読込。 df.shape は (564, 112)、 df.dtypes で「object 型に紛れている数値列」 を発見。 ここで 30 分。 取り込みの段階で躓くと半日が無駄になるので、 焦らず確認する。
09:30 〜 10:30 (型変換と単位統一): 「数値だが object 型」 になっていた 7 列を pd.to_numeric(errors='coerce') で float64 に統一。 7 列のうち 2 列で「N/A」 という文字列を発見し、 NaN に変換。 都道府県・地域ブロックの 2 列を category 型へ。 「人」 と「万人」 が混在する人口・所得列に、 派生列 (サフィックス付き) を追加。 ここで 1 時間。 単位の整備が分析の質を底上げするので、 焦らず時間をかける。
10:30 〜 11:30 (欠損の可視化と方針決定): df.isna().mean() で列別の欠損率を計算、 棒グラフで降順表示。 上位 4 列 (A8104, A8105, A6203, A4101) で欠損率 1% 超を確認。 欠損のパターンが「特定の年度に集中」 していることを df.groupby('年度').isna().mean() で発見。 「古い年度では一部の指標が未整備」 という背景を理解。 単純削除ではなく欠損フラグ列を作って後段に伝える方針に決定。 ここで 1 時間。 欠損のパターンを理解する作業は地味だが、 ここで手を抜くと後段の分析で必ず躓く。
11:30 〜 12:30 (外れ値の検出と扱い決定): np.log1p で人口・所得を対数変換、 IQR 法で外れ値を判定。 上位 5 件が東京・大阪・愛知・神奈川・福岡だったため「都市の特殊性」 として保持。 「IQR × 3 を超える行はフラグだけ立てて削除しない」 という方針をクレンジングログに記録。 ここで 1 時間。 外れ値判定は ドメイン知識との対話 が肝になる。
12:30 〜 13:30 (休憩 + 派生列設計): 昼休憩のあと、 派生列 (1 人あたり所得、 高齢化率、 合計特殊出生率、 人口密度) の設計と命名規約の整備。 「元列名 + 単位サフィックス」 のルールで一貫させる。 ここで 1 時間。 派生列の命名規約はチーム内で揉めることが多いので、 早めに決めて文書化する。
13:30 〜 14:00 (整合性検証とログ書き出し): 「1 人あたり所得 × 人口 = 総所得」 が ±0.5% 以内で一致することを assert で検証。 クレンジングログ (列名・操作・件数・理由) を JSON に書き出し、 git にコミット。 ここで 30 分。 整合性検証は短時間で完了するが、 後工程の信頼性を大きく上げる。
14:00 〜 14:30 (parquet 書き出しと検収): クレンジング後の DataFrame を parquet で保存し、 再読込して型・欠損・派生列が保持されていることを確認。 「半日かけたクレンジングが、 翌日も再現できる」 状態を担保。 ここで 30 分。 parquet の採用は地味だが、 「毎回クレンジングし直す」 という不毛から解放してくれる。
振り返り: 半日で「取り込み・型変換・単位統一・欠損確認・外れ値判定・派生列・整合性検証・ログ・parquet 化」 まで完了。 SSDSE-B-2026 のような整備済みデータでさえこれだけかかる。 自前のログデータや社内 DB から取り込んだデータなら、 倍以上の時間がかかると見積もるのが現実的。 クレンジングに時間を投資することは、 後段の分析・モデリング・レポートの品質を底上げする、 最もリターンの大きい投資である。
📕 関連語ミニ辞典 (12 語、 R516 追補)
クレンジングの周辺で頻出する用語を 12 語、 短い定義 + SSDSE-B-2026 での具体例で整理する。 既存の「関連用語辞典 10 語」 と合わせて 22 語の小辞典になる。 SSDSE 実践時にどの用語が必要になるかを確認しながら読み進めるとよい。
BOM (Byte Order Mark): UTF-8 ファイルの先頭に付く識別バイト。 utf-8-sig で開かないと、 列名先頭に「\\ufeff」 が混入する。 SSDSE 系の CSV では BOM 付きが多い。
category 型: pandas でカテゴリ変数を表す型。 メモリ消費が大幅に減り、 groupby が高速化する。 都道府県・地域ブロックは必ず category 型へ。
errors='coerce': pd.to_numeric 等で「変換不能セルを NaN にする」 引数。 例外を抑制し、 「どこで失敗したか」 を後段で集計可能にする。 クレンジングでは事実上必須。
欠損フラグ列: 「元値が欠損だった」 ことを 0/1 で記録する派生列。 補完後も「欠損由来か実値か」 を区別できるようにする。 SSDSE で欠損が 1% 超の列に推奨。
主キー: 行を一意に識別する列 (or 列の組合せ)。 SSDSE-B-2026 では「年度 × 都道府県」 が主キー。 重複検出と join の前に必ず宣言する。
派生列: 既存列から計算した新規列。 「1 人あたり所得」 「人口密度」 など。 命名規約と単位サフィックスを揃えるのがコツ。
parquet: 型情報を保持する列指向の保存形式。 クレンジング完了後の標準保存先として CSV より優れる。 SSDSE クレンジング後の中間ファイルに最適。
missingno: 欠損パターンの可視化ライブラリ。 列ごと・行ごとの欠損を 1 枚の絵で確認できる。 クレンジング初動の必須ツール。
MICE (多重代入): 欠損を複数回ランダムに補完して分散を保つ補完法。 「平均代入では分散が縮む」 問題を回避する。 sklearn の IterativeImputer が代表実装。
Winsorization: 外れ値を「削除せず、 一定範囲に丸める」 手法。 例: 上位 1% を 99 パーセンタイル値で打ち止めにする。 削除より情報損失が少ない。
クレンジングログ: 「何を、 なぜ、 何件、 削除・補完したか」 を記録する JSON or CSV。 再現可能性とレビュー対応速度を大幅に向上させる。
整合性検証 (sanity check): 派生列同士で「成立すべき関係」 を assert で確認する作業。 「1 人あたり所得 × 人口 = 総所得」 等。 短時間で大きな安心を得られる。
🎒 持ち帰り 10 か条 (本ページの要点まとめ)
本ページで学んだ内容のうち、 実務に持ち帰ってほしい要点を 10 か条にまとめる。 自分のクレンジング規約の最初のページにそのまま貼ってもよい。 SSDSE-B-2026 を題材にしつつ、 普遍的に通用する原則として整理した。
- 取り込みは
utf-8-sig で: BOM 付き UTF-8 を確実に読むため、 SSDSE 系では encoding='utf-8-sig' を既定に。
- 主キーを最初に宣言する: SSDSE-B-2026 は「年度 × 都道府県」。 重複検出と join の前提として明示。
- 型統一は
pd.to_numeric(errors='coerce') + astype('category'): 数値列とカテゴリ列を早めに区別。
- 欠損は「フラグ列を作って残す」: 単純削除や平均代入は分散歪みを起こす。 欠損フラグで情報を残す。
- 外れ値は対数変換 + IQR × 3: 人口・所得など右裾の長い分布で IQR × 1.5 は過剰削除。
- 派生列の命名規約を統一: 「元列名 + 単位サフィックス」 で一貫させ、 後段のグラフ・モデルでの誤読を防ぐ。
- 整合性検証を assert で書く: 「1 人あたり所得 × 人口 = 総所得」 が ±1% で一致することを必ず確認。
- クレンジングログを JSON で残す: 列名・操作・件数・理由を記録し、 git にコミットする。
- parquet/feather で保存: CSV は型情報が崩れる。 クレンジング後は型を保つ形式で。
- クレンジングはコードで残す: Excel の手動編集は再現できない。 必ず Python スクリプトに。
この 10 か条を満たせば、 SSDSE-B-2026 を使った分析プロジェクトは「再現可能で、 査読に耐え、 同僚に渡せる」 品質に到達できる。 クレンジングは目立たないが、 全体の質を決める作業。 ぜひ本ページの内容を自分の現場に持ち帰ってほしい。
📨 クロージング: 次の一歩
本ページを読んだ後の「次の一歩」 を整理しておく。 SSDSE-B-2026 を題材にしたクレンジングは、 単独で完結する作業ではなく、 続く「特徴量設計」 「モデリング」 「レポーティング」 へとつながる流れの最初の関門だ。 ここで身につけた習慣は、 他のデータセット (自治体のオープンデータ、 企業の内部 DB、 IoT のセンサーログ等) でも、 そのまま使える。
次の一歩 (1): 自分の手元のデータで「ステップ 1 〜 9」 を 1 回通してみる。 半日かかっても良いので、 ログを残す習慣を身につける。 SSDSE-B-2026 ではない自前のデータでこそ、 本ページの内容が活きる。
次の一歩 (2): チーム内で「クレンジング規約」 を整備する。 本ページの「持ち帰り 10 か条」 と「追加の落とし穴 8 件」 をたたき台に、 自分のチームの実情に合わせてカスタマイズしよう。 規約があるだけで、 新メンバーのオンボーディング期間が劇的に短くなる。
次の一歩 (3): 関連用語 (欠損メカニズム、 PPDAC サイクル、 特徴量) へ進む。 本ページ末尾の「関連用語」 セクションから、 自分の理解の弱い順にリンクをたどると効率的だ。 クレンジングの周辺知識を厚くすることが、 結果的にクレンジングの質を底上げする。
最後に: クレンジングは「捨てる」 ではなく「整える」 作業である。 この一言を腹落ちさせれば、 個別の操作のブレが激減する。 SSDSE-B-2026 を起点にして、 自分のデータサイエンス実践の土台を、 ぜひ強くしてほしい。
さらに踏み込む方へ: 本ページの内容を腹落ちさせたあとは、 「クレンジング規約のテンプレートを 1 枚にまとめて社内 Wiki に貼る」 「クレンジングスクリプトに pytest を仕込み CI で回す」 「parquet の中間ファイルを DVC で版管理する」 という 3 つのプラクティスに挑戦してほしい。 SSDSE-B-2026 のような公開データを使うときも、 この 3 点を入れるだけで、 プロジェクトのスケールに応じた品質保証ができるようになる。 教育用途であれ研究用途であれ、 「再現性」 と「品質」 を両立する設計は、 今後のデータサイエンスで最も投資価値の高いスキルセットになるはずだ。 本ページを起点にして、 自分の現場のクレンジング標準を、 ぜひ一段強くしてほしい。
本ページ全体のまとめ: データクレンジングとは、 取り込み・型変換・単位統一・欠損処理・外れ値判定・派生列・整合性検証・ログ・parquet 書き出しまでの一連の流れを、 再現可能なコードとして残す作業である。 SSDSE-B-2026 を題材にすれば、 重複 0・欠損 0・大都市の外れ値といった現象を通じて、 教科書では学べない「現場の判断」 を体験できる。 本ページの各セクション (図 1〜3、 表 1〜4、 理解度チェック 10 問、 ワークフロー 9 ステップ、 追加落とし穴 8 件、 事例集 6 件、 設計哲学 6 つ、 ナラティブ、 ミニ辞典 12 語、 持ち帰り 10 か条、 クロージング) を順に読み返せば、 自分のチームのクレンジング規約の骨格がそのまま出来上がる。 SSDSE-B-2026 を 1 回まわすところから、 ぜひ実践を始めてほしい。 そして本ページの内容を、 自分の現場の規約・スクリプト・社内 Wiki に落とし込んでこそ、 学びが定着する。 クレンジングという土台仕事に時間と頭を投じることが、 結局のところ分析プロジェクト全体の最大投資効率になる。
🗺 概念マップ
データクレンジングを中心に、 上位のデータエンジニアリング、 入力 (CSV / SSDSE / DB エクスポート)、 兄弟の前処理工程 (欠損 / 外れ値 / 型変換)、 出力 (Tidy data / DataFrame / parquet)、 そして利用先の分析・可視化・モデリングを放射状に整理した。
🔧 データクレンジング応用ブロック
以下はデータクレンジングを「業務・研究・教育」の現場で運用するための応用ブロック。 SSDSE-B-2026 を題材に追加の narration コード・応用レシピ・FAQ を補強。
このコードでやること: SSDSE-B-2026 のカテゴリ列「都道府県」を One-Hot エンコードして 47 列の 0/1 行列にする。
📥 入力データ: data/raw/SSDSE-B-2026.csv(2023 年抜粋)
| d23 = df[df['年度']==2023][['都道府県','総人口','出生数']].copy()
onehot = pd.get_dummies(d23, columns=['都道府県'])
print('元: 3 列, 変換後:', onehot.shape[1], '列')
print(onehot.iloc[:2, :7].to_string(index=False)) |
📤 実行結果:
元: 3 列, 変換後: 49 列
総人口 出生数 都道府県_三重県 都道府県_京都府 都道府県_佐賀県 都道府県_兵庫県
5092000 24430 False False False False
1184000 5696 False False False False
💬 2 + 47 = 49 列に拡張される。 機械学習モデルに投入する前の必須前処理。 sklearn の OneHotEncoder の方が pipeline と相性が良い。
このコードでやること: SSDSE-B-2026 の総人口を 3 種類のスケーリング手法で比較する。
📥 入力データ: data/raw/SSDSE-B-2026.csv(2023 年)
| from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
d23 = df[df['年度']==2023].copy()
s = d23[['総人口']].values
z = StandardScaler().fit_transform(s).flatten()
mm = MinMaxScaler().fit_transform(s).flatten()
rb = RobustScaler().fit_transform(s).flatten()
print('東京の値:')
i = d23.index[d23['都道府県']=='東京都'][0]
loc = list(d23.index).index(i)
print(f'Z={z[loc]:.2f}, MinMax={mm[loc]:.2f}, Robust={rb[loc]:.2f}') |
📤 実行結果:
東京の値:
Z=4.13, MinMax=1.00, Robust=7.82
💬 Z 標準化では東京が +4σ、 MinMax では 1.0(最大値)、 Robust では IQR の約 8 倍。 Robust が「外れ値を保持しつつ尺度を揃える」のに最適。
このコードでやること: great_expectations 風の検証関数を自作し、 SSDSE-B-2026 の必須性質を assert する。
📥 入力データ: data/raw/SSDSE-B-2026.csv
| def validate_ssdse(df):
assert df.shape == (564, 112), f'shape: {df.shape}'
assert df['都道府県'].nunique() == 47
assert df['年度'].between(2012, 2023).all()
assert (df['総人口'] > 0).all()
assert df.duplicated(subset=['年度','都道府県']).sum() == 0
return True
ok = validate_ssdse(df)
print('SSDSE-B-2026 検証合格:', ok) |
📤 実行結果:
SSDSE-B-2026 検証合格: True
💬 関数 1 つで「想定どおりのデータか」を機械的に確認。 CI(GitHub Actions)に組み込めば、 上流データの破損を即時検知できる。
⚙️ 応用 25 連発(既出 25 + 応用 25 = 計 50 を補完)
- isort + black で前処理コードを統一スタイルに
- pre-commit hook で品質チェック
- tox で複数 Python バージョン互換性検証
- mypy で型チェック
- pylint / ruff で静的解析
- sphinx で前処理関数を自動ドキュメント化
- nbdev でノートブック → ライブラリ変換
- kedro でデータパイプラインのテンプレート化
- Prefect / Dagster で workflow 定義
- Airflow Operator で日次クレンジング
- PostgreSQL の COPY で大量取込前にクレンジング
- BigQuery の SQL でクレンジング (REGEXP_REPLACE)
- Snowflake で COPY INTO + TRANSFORM
- dbt で「クレンジング SQL」を再利用可能化
- Apache Iceberg で大規模 clean データ管理
- Delta Lake で時間旅行 (time travel) クレンジング履歴
- cleanlab でラベル品質チェック
- fastai の DataBlock で画像/テキストクレンジング
- NLTK + spacy で日本語テキスト正規化
- sudachi で日本語形態素解析
- mecab-ipadic-neologd で表記揺れ正規化
- jaconv で全角半角・カタカナ変換
- unicode_jp 正規化
- CSV 文字コード判定の高速化(charset-normalizer)
- AWS Glue DataBrew でノーコード前処理
🌟 追加 FAQ 10 問
Q1. great_expectations と pandera どちらを選ぶ?
great_expectations は大型・柔軟、 pandera は pydantic 風で軽量。 小規模なら pandera。
Q2. クレンジング後のレポートを自動生成したい
pandas-profiling / sweetviz / ydata-profiling で HTML レポート。
Q3. 業務担当者にレビューしてもらうには?
Streamlit で対話可視化 → 不整合行を一覧表示してフィードバックを受ける。
Q4. クレンジングの結果が再現できない
乱数 seed 固定、 pandas/numpy バージョン固定、 ライブラリ更新ログを残す。
Q5. 外れ値除外で結論が変わる
sensitivity analysis を実施。 外れ値あり/なし両方で結論が一致するか確認。
Q6. クレンジングを SQL でやるべき?
集約・結合が中心なら SQL、 ML 前処理なら pandas/sklearn。 dbt で SQL を再利用可能に。
Q7. 1 度きりの分析ならノートブックで OK?
OK。 ただし「翌年も同じ分析」を想定するなら関数化。
Q8. クレンジングの失敗を防ぐコードレビュー観点
(1) 順序 (2) 副作用 (3) NaN 扱い (4) 単位 (5) 主キー指定。
Q9. クレンジングをドキュメント化するには
Markdown + Mermaid で工程図、 各関数 docstring。
Q10. 業務的に正しいクレンジングと統計的に正しいクレンジングの両立
両方の指標を並べる。 例: 「業務基準では外れ値、 統計的には正常値」を脚注に。
🛠 トラブルシューティング表
| 症状 | 原因 | 対策 |
|---|
| 行数が想定より多い | 重複未削除 | drop_duplicates(subset=) で主キー指定 |
| 数値列が object 型 | "," や空白混入 | to_numeric(errors='coerce') で強制変換 |
| NaN が数値演算で 0 になる | fillna(0) を行ったのを忘れた | コード履歴を確認、 別フラグ列を残す |
| 外れ値除外で精度が低下 | 本来の信号を除去 | sensitivity analysis を実施 |
| 日付が 1970-01-01 | 空文字を to_datetime した | errors='coerce' で NaT に |
| カテゴリ列がメモリ爆発 | 値の種類が多すぎる | category dtype に変換 |
🧪 ラボノート(再現実験ステップ)
- SSDSE-B-2026 を読み込み
- df.shape == (564, 112) を assert
- df.isna().sum() で欠損率確認
- df.duplicated(subset=['年度','都道府県']).sum() == 0 を assert
- df.dtypes で型確認、 必要に応じて astype
- 主要数値列の describe() で異常検査
- 対象指標で IQR / Z スコア外れ値検出
- 前処理 pipeline を関数化
- 関数を pytest で回帰テスト
- 結果を data/processed/ に UTF-8 BOM CSV で保存
🚧 クレンジングパイプライン設計
A. 8 ステップ汎用パイプライン表
| ステップ | 入力 | 操作 | 出力 | 検証 |
| 取り込み | CSV | read_csv | raw df | shape 確認 |
| 列名統一 | raw df | rename | renamed df | columns assert |
| 型変換 | renamed df | astype / to_datetime | typed df | dtypes 確認 |
| 重複削除 | typed df | drop_duplicates | unique df | 主キー一意性 |
| 欠損処理 | unique df | fillna / dropna | no-na df | 欠損 0 確認 |
| 外れ値処理 | no-na df | clip / IQR | clipped df | 値域確認 |
| 正規化 | clipped df | StandardScaler | scaled df | mean 0, std 1 |
| 保存 | scaled df | to_csv | clean CSV | reload 検証 |
B. SSDSE-B-2026 用パイプライン関数の実装
このコードでやること: 1 つの関数で SSDSE の前処理を pipeline 化し、 結果と中間検証を出す。
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行)
都道府県 SSDSE-B-2026(年度) Prefecture(都道府県) A1101(総人口)
北海道 2,023 北海道 5,092,000
東京都 2,023 東京都 14,086,000
沖縄県 2,023 沖縄県 1,468,000
…(全 47 行)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | import pandas as pd
from sklearn.preprocessing import StandardScaler
def cleanse(df):
df = df.copy()
df = df.rename(columns={'年度':'year','都道府県':'pref','総人口':'pop_total'})
df['year'] = df['year'].astype('int32')
df = df.drop_duplicates(subset=['year','pref'])
df = df.dropna(subset=['pop_total'])
scaler = StandardScaler()
df['pop_z'] = scaler.fit_transform(df[['pop_total']])
return df
raw = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
clean = cleanse(raw)
print('clean shape:', clean.shape)
print(clean[['year','pref','pop_total','pop_z']].head(3).to_string(index=False)) |
📤 実行結果:
clean shape: (564, 113)
year pref pop_total pop_z
2023 北海道 5092000 0.879082
2022 北海道 5140000 0.896245
2021 北海道 5183000 0.911621
💬 pipeline 関数は idempotent(何度呼んでも同じ結果)に作る。 sklearn の Pipeline クラスを使うと前処理 + モデル訓練を一体化できる。
🛡 検証フレームワーク比較
A. 8 フレームワーク比較
| フレームワーク | 特徴 | 記述スタイル | 主な検証 |
| great_expectations | 大型・SaaS 連携 | JSON 設定 | 列値域・型・行数・欠損率・正規表現 |
| pandera | 軽量・Python ネイティブ | クラス定義 | 型・nullable・unique・check 関数 |
| cerberus | 辞書ベース | YAML | スキーマ検証 |
| voluptuous | 関数合成 | Python 関数 | JSON 風検証 |
| marshmallow | シリアライズ前提 | クラス | API ペイロード検証 |
| pydantic | 型ヒント中心 | BaseModel | 型・自動変換 |
| Apache Griffin | 大規模分散 | JSON | Hadoop 上の品質指標 |
| DeepChecks | ML 専用 | スクリプト | データドリフト検出 |
B. pandera で SSDSE スキーマ検証
このコードでやること: pandera で SSDSE-B-2026 の主要列に型・値域制約を宣言し、 自動検証。
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行)
都道府県 SSDSE-B-2026(年度) Prefecture(都道府県) A1101(総人口) A4101(出生数)
北海道 2,023 北海道 5,092,000 24,430
東京都 2,023 東京都 14,086,000 86,348
沖縄県 2,023 沖縄県 1,468,000 12,549
…(全 47 行)
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | import pandera as pa
from pandera import Column, DataFrameSchema, Check
schema = DataFrameSchema({
'年度': Column(int, Check.in_range(2012, 2023)),
'都道府県': Column(str),
'総人口': Column(int, Check.greater_than(0)),
'出生数': Column(int, Check.greater_than_or_equal_to(0)),
})
import pandas as pd
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
validated = schema.validate(df[['年度','都道府県','総人口','出生数']])
print('検証合格:', validated.shape) |
📤 実行結果:
検証合格: (564, 4)
💬 検証エラーが出ると SchemaError 例外で停止する。 CI に組み込めば「データ品質劣化」を本番デプロイ前に防げる。
🔗 隣接手法への橋渡し
データクレンジングは収集と特徴量エンジニアリングの間の橋。 3 視点 (接続・統合・比較) で隣接前処理工程との関係を整理する。
🔌 接続: 上流・下流での連鎖
🧩 統合: 前処理パイプラインへの組み込み
読み込み (read_csv で SSDSE-B-2026 を取得) → 列名正規化 → 型変換 (parse_dates・dtype) → 欠損処理 (median/前後補完) → 重複削除 → 値の妥当性検証 (range/codeset) の流れで、 sklearn Pipeline 化することで再現性が確保できる。 各段で検証ログを残すと、 後工程の異常検知時に原因切り分けが速い。
⚖️ 比較: 隣接前処理工程との位置づけ
| 工程 | 主目的 | 典型操作 | 位置 |
| データクレンジング | 誤り・欠損の除去 | 欠損補完・型変換・重複削除 | 収集直後 |
| 特徴量エンジニアリング | モデル入力作成 | 変数生成・スケーリング・エンコード | クレンジング後 |
| データ統合 | 複数源の統合 | 結合・名寄せ・スキーマ統一 | クレンジング前後 |
| EDA | 分布・関係の把握 | 可視化・要約統計 | クレンジング後 |
4 工程は目的が異なる。 クレンジングは「正しさ」、 特徴量エンジニアリングは「有用性」、 統合は「整合性」、 EDA は「理解」を担う。 SSDSE 分析では順にクレンジング → 統合 → EDA → 特徴量化と進めるのが定型。
🌳 手法選択フロー
データクレンジングは欠損・外れ値・型統一を反復する前処理工程。
- 欠損値の扱いは? Yes → 欠損値、 No → 欠損メカニズム を先に確認
- 外れ値や重複は? Yes → 外れ値、 No → 重複処理 を先に確認
- 型や単位は揃ったか? Yes → データ型、 No → 正規化 を先に確認
スクリプト主導なら pandas、 大規模なら Spark、 GUI なら OpenRefine、 と「データ規模と対話性」で選ぶ。
🎮 触って理解する
架空の店舗売上データ(8行)には、 表記揺れ・重複行・型混在・欠損・異常値 の 5 種類の「汚れ」が仕込んである。 下のボタンを ①→⑤の順 に押すと、 クレンジングの各工程が 1 つずつ適用され、 表・棒グラフ・集計値(件数/合計/平均)がリアルタイムに変化する。 行をタップ/クリック すると、 その行に潜む問題の説明が表示される。 汚れたまま集計した平均と、 クレンジング後の平均がどれだけ違うかに注目してほしい。
行をタップ/クリックすると、 その行の問題点がここに表示されます。
📓 クレンジングログ(適用したルールの記録 = 再現性の担保)
- まだ何も適用されていません。 ①から順に押してください。
💡 直感: 「分析の 8 割は前処理」の意味
上の演習で分かる通り、 集計コード自体は 1 行 (平均を取るだけ) なのに、 その前に 5 工程の掃除が必要だった。 これが「分析工数の 60-80% は前処理」と言われる実態である。 しかも汚れたまま計算した平均 (1,613.3 万円) とクレンジング後の平均 (790 万円) は 2 倍以上ずれる。 計算機はエラーを出さずに「間違った答え」を静かに返すため、 汚れは自分で探しに行くしかない — これが GIGO (Garbage In, Garbage Out) の恐ろしさである。
⚠️ よくある落とし穴
- 過剰な削除: ⑤で札幌の 5800 を「異常だから」と行ごと削除すると、 実在する店舗のデータが消える。 上の演習では原簿と照合して 580 に修正した。 IQR や Z スコアは「疑わしい値の検出器」であって「自動削除装置」ではない (外れ値 参照)。 欠損も同様に、 闇雲な dropna は標本を偏らせる (欠損値 参照)。
- 元データの破壊: 生データの CSV を直接上書き保存すると、 「⑤の修正が正しかったか」を後から検証できない。 元データは読み取り専用で保管し、 クレンジング後は別ファイルに書き出すのが鉄則。
- ルールの記録漏れ: 上の「クレンジングログ」のように、 どの値をどんな根拠で直したかを残さないと、 半年後の自分もレビュアーも再現できない。 手作業の Excel 修正が最も危険で、 コード化 (= 記録) されたクレンジングだけが再現可能である。
🚀 発展: バリデーション・パイプライン化・再現性
- バリデーション: クレンジング後に「行数 6・売上は 0〜10000 の数値・欠損 0」といった期待条件を assert やスキーマ (pandera / Great Expectations) で検証し、 品質ゲートとして自動化する (バリデーション 参照)。
- パイプライン化: ①〜⑤を関数の連鎖として実装すれば、 データが更新されても同じ順序・同じルールで再実行できる。 順序が重要な点 (欠損補完の後に外れ値判定をすると基準が歪む等) はコードの順序として固定される (ETL / データクレンジング詳細 参照)。
- 再現性: 「生データ + クレンジングコード + ログ」の 3 点セットが揃えば、 誰がいつ実行しても同じ
D_clean が得られる。 これが分析の信頼性の土台であり、 クレンジング後の EDA やモデリングの結論を守る保険になる。