ClaudeCodeでデータクレンジングを自動化する方法【欠損値・重複・表記揺れ対応】
データ分析の現場で「分析に8割の時間がかかっているはずなのに、実際の作業の8割は前処理」とよく言われます。CSVを開けば欠損値だらけ、社名は「(株)」「株式会社」「Inc.」がバラバラ、電話番号にハイフンが付いたり付かなかったり、住所表記もカオス。気が遠くなる作業ですが、ClaudeCodeを使えば、こうしたデータクレンジングを大幅に自動化できます。本記事では、欠損値・重複・表記揺れという代表的な3つの課題に対し、ClaudeCodeで処理する手順と、生成させるPandasコードの実例を詳しく解説します。非エンジニアでも実行できる形にまとめていますので、明日からの業務にそのまま使えます。
結論:クレンジングは「診断→ルール作成→コード生成」の3ステップで完結
最初に結論をお伝えします。ClaudeCodeでデータクレンジングを行うベストな進め方は、データを一気に修正させるのではなく、3つのステップに分けることです。
第1ステップは「データ診断」で、ClaudeCodeにCSVを読ませて品質レポートを出力させます。欠損率、重複件数、表記揺れの候補、外れ値などを一覧化します。第2ステップは「ルール作成」で、診断結果をもとに「この列の欠損は中央値で埋める」「会社名は『株式会社○○』に統一」といった処理方針を決めます。第3ステップは「コード生成と実行」で、決めたルールに従ったPandasコードをClaudeCodeに書かせて実行します。この3ステップに分けると、処理の透明性が高く、後から「なぜこの値になったか」を追えるようになります。本記事ではこの流れに沿って、具体的なプロンプトとコード例を順番に解説します。
クレンジング前に整える環境とディレクトリ構成
データクレンジングを始める前に、最低限の環境を整えます。Python 3.10以上とPandas、できればNumpyとopenpyxlも入れておきます。
pip install pandas numpy openpyxl jellyfish python-dateutil
ディレクトリ構成は次のようにすると、後の自動化が楽になります。
data-cleansing/
├── raw/ # 元データ(読み取り専用)
├── interim/ # 中間データ
├── clean/ # 完成データ
├── reports/ # 診断レポート
├── scripts/ # 生成されたスクリプト
├── rules/
│ └── cleansing-rules.md # クレンジングルール
└── CLAUDE.md
raw/はGitやエクスプローラーで読み取り専用にしておきます。「元データを絶対に上書きしない」というのはデータ分析の鉄則です。rules/cleansing-rules.mdには案件ごとの処理方針を残し、再現性を担保します。
ステップ1:データ診断プロンプト
最初にやるのは、データの全体像を把握する診断です。
プロンプト1:基本診断プロンプト
raw/customers.csv を読み込み、以下の項目で品質レポートを作成してください。
出力先: reports/customers-diagnosis.md
1. 行数・列数・各列のデータ型
2. 各列の欠損数と欠損率
3. 各列の重複件数
4. 文字列列の値ユニーク数と出現頻度トップ10
5. 数値列の最小・最大・平均・中央値・標準偏差
6. 日付列の最古・最新
7. 表記揺れの可能性が高い列とその例
8. 異常値(外れ値)の候補
9. 推奨されるクレンジング処理を箇条書きで5つ
このプロンプトを投げると、たとえば次のようなレポートが返ってきます。
## 品質レポート
- 行数: 12,453
- 列数: 18
- 欠損率トップ:
- phone: 32.4%
- fax: 78.1%
- 重複行: 213件
- 表記揺れ疑い列:
- company_name: 「(株)山田」「株式会社山田」「(株)山田」が混在
- prefecture: 「東京」「東京都」が混在
- 推奨処理:
1. companyの法人格表記を「株式会社」に統一
2. prefectureに「都府県」サフィックスを統一
3. 重複行の削除(メールアドレスをキー)
4. phoneを「090-0000-0000」形式に統一
5. 日付列を ISO 8601 に統一
このレポートを見れば、次のステップで何をすべきかが明確になります。
プロンプト2:列ごとの深掘り診断
reports/customers-diagnosis.md の中で、特に表記揺れの多い列について
具体的な値のリストとクラスタリング結果を出してください。
- ジャロ・ウィンクラー距離が0.85以上の値を同一クラスタとして提示
- 各クラスタの代表値(最頻出)を推奨統一表記として併記
このプロンプトを使うと、「実は同じものを指しているのに表記がバラバラ」な値を自動でグルーピングしてくれます。
ステップ2:ルール作成プロンプト
診断結果をもとに、処理ルールを文書化します。
プロンプト3:クレンジングルール作成
reports/customers-diagnosis.md を読み込み、
rules/cleansing-rules.md を作成してください。
各ルールは次の形式で書いてください:
- 対象列
- 処理内容
- 例外条件
- 失敗時の挙動(スキップ/エラー停止/ログのみ)
ルールは10〜15個に絞り、優先度の高いものから並べてください。
生成されるルールの例は次のようになります。
## クレンジングルール
### ルール1: 会社名の法人格統一
- 対象列: company_name
- 処理内容: 「(株)」「(株)」「㈱」を「株式会社」に統一し、社名の前に配置
- 例外条件: 「有限会社」「合同会社」はそのまま
- 失敗時: ログ出力のみで処理継続
### ルール2: 都道府県の正規化
- 対象列: prefecture
- 処理内容: 「東京」→「東京都」、「大阪」→「大阪府」、「北海道」はそのまま
- 例外条件: 海外住所(country列がJP以外)はスキップ
- 失敗時: ログ出力のみで処理継続
文書化することで「なぜこの処理をしたか」が後で必ず追えるようになり、レビューや監査にも対応できます。
ステップ3:Pandasコード生成プロンプト
ルールが固まったら、いよいよコード生成です。
プロンプト4:クレンジングスクリプト生成
rules/cleansing-rules.md に従って、Pandasでデータクレンジングを行う
Pythonスクリプトを生成してください。
要件:
- 入力: raw/customers.csv
- 出力: clean/customers.csv
- 各ルールごとに関数を分離
- 関数名は clean_<列名> 形式
- ログ出力(処理件数、変更件数、スキップ件数)
- 元データは絶対に書き換えない
- 処理途中で例外が起きてもログを残して継続
- 最後にサマリーを print
出力先: scripts/cleansing.py
生成されるコードのイメージは以下のとおりです。
import pandas as pd
import re
from pathlib import Path
INPUT = Path("raw/customers.csv")
OUTPUT = Path("clean/customers.csv")
OUTPUT.parent.mkdir(exist_ok=True)
def clean_company_name(df: pd.DataFrame) -> pd.DataFrame:
pattern = re.compile(r"^[((]?株[))]?|㈱")
before = df["company_name"].copy()
df["company_name"] = df["company_name"].str.replace(pattern, "", regex=True)
df["company_name"] = "株式会社" + df["company_name"].str.strip()
changed = (before != df["company_name"]).sum()
print(f"clean_company_name: {changed}件変更")
return df
def clean_prefecture(df: pd.DataFrame) -> pd.DataFrame:
mapping = {
"東京": "東京都", "大阪": "大阪府", "京都": "京都府",
}
before = df["prefecture"].copy()
df["prefecture"] = df["prefecture"].replace(mapping)
changed = (before != df["prefecture"]).sum()
print(f"clean_prefecture: {changed}件変更")
return df
def clean_phone(df: pd.DataFrame) -> pd.DataFrame:
def normalize(p):
if pd.isna(p):
return p
digits = re.sub(r"\D", "", str(p))
if len(digits) == 11:
return f"{digits[:3]}-{digits[3:7]}-{digits[7:]}"
if len(digits) == 10:
return f"{digits[:2]}-{digits[2:6]}-{digits[6:]}"
return p
df["phone"] = df["phone"].apply(normalize)
return df
def dedupe(df: pd.DataFrame) -> pd.DataFrame:
before = len(df)
df = df.drop_duplicates(subset=["email"], keep="first")
print(f"dedupe: {before - len(df)}件削除")
return df
def main():
df = pd.read_csv(INPUT)
print(f"読み込み: {len(df)}件")
df = clean_company_name(df)
df = clean_prefecture(df)
df = clean_phone(df)
df = dedupe(df)
df.to_csv(OUTPUT, index=False)
print(f"出力: {len(df)}件 -> {OUTPUT}")
if __name__ == "__main__":
main()
このスクリプトをそのまま実行すれば、ルールに従ったクレンジングが完了します。
欠損値処理の具体プロンプト
欠損値の扱いは、データ分析の品質を左右する重要ポイントです。
プロンプト5:欠損値処理プロンプト
以下の方針で欠損値を処理するコードを生成してください。
- 数値列 income, age: 中央値で埋める
- カテゴリ列 prefecture: 最頻値で埋める
- 任意列 fax: 欠損率70%超のため列ごと削除
- 日付列 registered_at: 欠損は「2020-01-01」で埋める
- メール列 email: 欠損行を除外(連絡不能のため)
各処理ごとに「埋める前の欠損数」「処理後の欠損数」をログ出力してください。
このようにルールベースで指定すると、コードが意図通りに動き、レビューもしやすくなります。
def fill_missing(df: pd.DataFrame) -> pd.DataFrame:
print(f"income 欠損: {df['income'].isna().sum()}")
df["income"] = df["income"].fillna(df["income"].median())
print(f"prefecture 欠損: {df['prefecture'].isna().sum()}")
df["prefecture"] = df["prefecture"].fillna(df["prefecture"].mode()[0])
if "fax" in df.columns:
df = df.drop(columns=["fax"])
df["registered_at"] = df["registered_at"].fillna("2020-01-01")
df = df.dropna(subset=["email"])
return df
重複除去の具体プロンプト
重複は単純な完全一致だけでなく、「ほぼ同じ」を検出することが重要です。
プロンプト6:あいまい重複検出プロンプト
顧客マスタの重複を以下の基準で検出するコードを生成してください。
- 完全一致: email
- ほぼ一致: 会社名(小文字化・記号除去後の編集距離2以下)
+ 電話番号(数字のみ抽出後の完全一致)
- 検出された重複候補は merge_candidates.csv に出力
- 自動マージはせず、人間レビュー前提
生成されるコードでは、jellyfishライブラリを使った類似度計算が組み込まれます。
import jellyfish
def normalize(s):
return re.sub(r"[^a-z0-9ぁ-んァ-ヶ一-龯]", "", str(s).lower())
def find_fuzzy_duplicates(df):
pairs = []
rows = df.to_dict("records")
for i in range(len(rows)):
for j in range(i + 1, len(rows)):
a = normalize(rows[i]["company_name"])
b = normalize(rows[j]["company_name"])
phone_a = re.sub(r"\D", "", str(rows[i]["phone"] or ""))
phone_b = re.sub(r"\D", "", str(rows[j]["phone"] or ""))
if jellyfish.levenshtein_distance(a, b) <= 2 and phone_a == phone_b:
pairs.append((rows[i], rows[j]))
return pairs
このように、自動マージではなく「候補出力+人間判断」のフローにすると、データを破壊するリスクを抑えられます。
表記揺れ統一の実践例
表記揺れはクレンジングで最も時間がかかる作業ですが、ClaudeCodeを使えば一気に短縮できます。
プロンプト7:表記揺れマッピング自動生成
データ内の company_name 列を読み、表記揺れと推測されるグループを作成し、
mapping.csv(「元表記,統一表記」の2列)を出力してください。
ルール:
- 「(株)」「(株)」「㈱」「株式会社」を統一
- 全角半角の混在を半角に
- 末尾の空白除去
- 大文字小文字の揺れを正規化(英字部分のみ)
- 同義語(例: NTT, エヌティティ)も同じグループに
確証が低いマッピングは confidence 列に low と記載してください。
生成されたmapping.csvを人間がレビューしたあと、replace処理で一括適用できます。
mapping_df = pd.read_csv("rules/mapping.csv")
mapping = dict(zip(mapping_df["元表記"], mapping_df["統一表記"]))
df["company_name"] = df["company_name"].replace(mapping)
このフローは「機械が候補を出し、人間が決め、機械が一括適用する」という分業構造になっており、品質と速度を両立できます。
実践チュートリアル:1万件の顧客マスタを30分でクレンジング
最後に、実際の業務を想定したチュートリアルを通しでお見せします。
シナリオ: 1万件の顧客マスタCSVがあり、社名・電話・住所がバラバラ。3日後の分析までに整える必要がある。
ステップ1: プロンプト1で診断レポートを出す(5分)。 ステップ2: プロンプト3でクレンジングルールを文書化する(5分)。 ステップ3: プロンプト4でスクリプトを生成し、テスト実行する(10分)。 ステップ4: プロンプト7で表記揺れマッピングを作り、レビュー(5分)。 ステップ5: 本番実行し、cleanディレクトリに保存(5分)。
合計30分で、人手なら丸2日かかる作業が完了します。実行ログは次のようになります。
読み込み: 10,234件
clean_company_name: 4,128件変更
clean_prefecture: 2,341件変更
clean_phone: 5,612件変更
fill_missing: income欠損 723→0, prefecture欠損 89→0
dedupe: 213件削除
出力: 10,021件 -> clean/customers.csv
最初は半信半疑でも、一度この流れを体験すると、データ前処理に対する恐怖心が一気に消えます。
FAQ
Q1. ClaudeCodeに生データを直接アップロードして大丈夫ですか? A1. データに個人情報や機密情報が含まれる場合、社内ポリシーに従って判断してください。判断に迷う場合はエンジニアに相談を。匿名化したサンプルで動作確認し、本番はローカル実行で完結させる構成が安全です。
Q2. 数百万行のデータでも処理できますか? A2. Pandasの限界(メモリ)に依存します。500万行を超える場合はDaskやPolarsの利用、もしくはチャンク処理を生成させましょう。
Q3. クレンジングルールはどう管理すれば良いですか? A3. rules/cleansing-rules.mdに集約し、Git管理することを推奨します。バージョン管理することで「いつ・誰が・なぜ」変更したかを追えます。
Q4. 表記揺れの統一が間違っていた場合の対処は? A4. mapping.csvに「元表記,統一表記,confidence」を残しているので、誤マッピングを書き戻すスクリプトを再生成すれば復元できます。元データを必ず保持しておくことが前提です。
Q5. 欠損値を埋めずに分析した方が良いケースは? A5. 欠損自体に意味がある(例: 未回答が信号)場合は埋めず、欠損フラグ列を追加するのが定石です。プロンプトで「欠損フラグ列を別途追加」と指定できます。
Q6. ExcelファイルでもCSVと同じ手順で行けますか? A6. はい。pd.read_excelで読み込み、複数シートはdict形式で扱います。「sheet_name=None」で全シート読み込みもできます。
Q7. 定期実行(毎週など)に組み込めますか? A7. 生成したcleansing.pyをスケジューラ(cron、Windowsタスクスケジューラ等)に登録すれば自動化できます。社内サーバーやクラウドでの実行ならエンジニアと相談を。
まとめ
ClaudeCodeでデータクレンジングを自動化する鍵は、「診断→ルール作成→コード生成」の3ステップに分けることです。一気にやらせず、各ステップで人間がレビューする運用にすることで、品質と再現性を両立できます。まずは小さなCSVから、診断プロンプトを1回投げてみてください。これまで何時間もかかっていた作業が、驚くほどあっさり終わる感覚を体験できるはずです。