mcpField
T
tabular-eda

tabular-eda

github.com/brojonatデータ・データベース135 回インストール1 週間前に更新
リポジトリ

tabular-eda について

tabular-edaは、モデリング前に表形式データを調査するスキルです。データ品質の問題を確認し、特徴量名と推奨対応を含む所見を、可視化とJSONレポートとともに出力します。

主な機能

  1. 01目的変数の型とタスクを推定
  2. 02欠損と分布を分析
  3. 03リークと冗長な特徴量を検出
  4. 04高カーディナリティ列と定数に近い列を特定
  5. 05プロットとfindings.jsonを生成

活用シーン

  1. 01新しいデータセットを調査
  2. 02モデル結果の異常を検証
  3. 03モデリング前にデータを確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/brojonat/llmsrules --skill tabular-eda

インストール後、Claude Code で/tabular-edaを入力して読み込まれたか確認します。

同梱ファイルscripts/demo.py

詳細

表形式データのEDA — 正しい進め方

新しい表形式データセットを渡されたら、まず立ち止まってください。すぐに XGBClassifier() に飛びついてはいけません。10 分間の EDA で、下流のモデルを台無しにしかねない問題を見つけられます。たとえば、ターゲットリーク、高カーディナリティの急増、MAR による欠損データ、ピアソン相関では役に立たないと判断される非線形特徴量などです。このスキルでは、そのワークフローを紹介します。

このスキルを使うとき

  • 新しいデータセットを受け取ったばかりで、どんなデータが含まれているか見当もつかないとき
  • モデルをトレーニングする前に、まずデータを検証したいとき
  • モデルの性能が不自然に高い(または低い)ため、データ品質の問題を疑っているとき
  • ユーザーから「このデータセットで何をすればよいですか?」と尋ねられたとき

このスキルを使わないとき

  • すでにデータセットのことを深く理解しており、プロファイリングも済んでいるとき
  • データセットが画像/テキスト/音声/時系列であるとき — 別のルールが必要です
  • ユーザーがリスクを承知のうえで、とにかく手早くモデルをトレーニングしたいだけのとき

ワークフロー

1. Load → shape, dtypes, memory
2. Identify the target → infer problem type (binary / multiclass / regression)
3. Missing data → per-column %, overall %, patterns
4. Numeric distributions → skew, outliers, scale mismatches
5. Categorical cardinality → flag high-cardinality (OHE explosion risk)
6. Near-constant features → flag and consider dropping
7. Redundant pairs → flag features with > 0.95 mutual correlation
8. **Target leakage detection** → flag features with > 0.95 |Pearson| to target
9. **Mutual information vs Pearson** → catch non-linear features Pearson misses
10. Optional: PCA / UMAP for low-dim visualization

出力は調査結果レポートです。疑わしい項目を、特徴量名、検出に使われた指標、推奨アクションとともに一覧にします。プロットを出力するだけでは不十分です。 名前の付いた問題の一覧があれば、それに基づいて対処できます。

チュートリアルとの違いを生む5つのポイント

1. ターゲットリークの検出 — EDA で最も価値の高いチェック

「リーク」特徴量とは、予測時点では実際には利用できないターゲット情報を含む特徴量です。典型例は次のとおりです。

  • made_payment を予測するための account_balance_after_payment
  • churned を予測するための total_charges(累積値)
  • claim_was_filed を予測するための claim_paid_amount

これらの特徴量は、予測時点より後に計算されます。これらを使ってトレーニングすると、テスト精度は99%になる一方で、本番環境では完全に失敗するモデルができてしまいます。兆候はターゲットとの相関が不自然なほど高いことです。0.95 を超えるものはリークの疑いがあり、0.99 を超えるものはほぼ確実にリークです。

def find_leakage_candidates(df, target_col, numeric_cols, threshold=0.95):
    out = []
    for col in numeric_cols:
        if col == target_col:
            continue
        corr = float(df[[col, target_col]].dropna().corr().iloc[0, 1])
        if abs(corr) > threshold:
            out.append({"feature": col, "pearson": round(corr, 4)})
    return out

リーク候補を見つけた場合は、削除する前に必ずデータ所有者に確認してください。特徴量が正当な理由でターゲットとほぼ完全に相関している場合もあります(たとえば、上流モデルによる予測値など)。ただし、まずは「これはリークだ」と考えるのが基本です。

2. 相互情報量とピアソン相関の比較 — 非線形シグナルを検出

ピアソン相関で捉えられるのは線形な関係だけです。sin(x) や (x - 0.5)² を介してターゲットに影響する特徴量は、ピアソン相関が ≈ 0 となり、ピアソン相関だけでは役に立たないと判断されます。相互情報量なら、線形・非線形の両方を捉えられます。

from sklearn.feature_selection import mutual_info_classif, mutual_info_regression

# For classification
mi_scores = mutual_info_classif(X, y, random_state=0)

# For regression
mi_scores = mutual_info_regression(X, y, random_state=0)

|Pearson| と MI を棒グラフで並べてプロットします。MI が高いのに |Pearson| が低い特徴量は、線形 EDA では見逃されている非線形シグナルです。こうした特徴量は線形モデルでは見えませんが、XGBoost では大きな効果を発揮します。

これは、回帰バンドルで Friedman1 の sin(π·x₀·x₁) 項を使って説明されるのと同じ教訓です。線形相関はゼロでも、相互情報量は大きく、ターゲットへの寄与も非常に大きくなります。

3. 高カーディナリティのカテゴリ特徴量の検出

数千の一意な値を持つ user_id のような列は、OneHotEncoder によって数千のスパース列へと膨れ上がります。一意な値が50個を超えるカテゴリ特徴量にはフラグを付けます。

def find_high_cardinality(df, cat_cols, threshold=50):
    return [
        {"feature": c, "n_unique": int(df[c].nunique())}
        for c in cat_cols if df[c].nunique() > threshold
    ]

高カーディナリティのカテゴリ特徴量に対する推奨アクション:

  • ターゲットエンコーディング(カテゴリごとのターゲット平均を平滑化) — 効果的ですが、注意を怠ると交差検証中にリークします
  • 頻度エンコーディング — 各カテゴリをその出現頻度に置き換えます
  • ハッシュエンコーディング — サイズ固定のハッシュバケットを使います
  • そのまま削除する — user_id は、そもそも役に立つ特徴量であることがほとんどありません
4. 準定数特徴量の検出

1つの値が行の98%を超えて占める列には、実質的にシグナルがありません。残しておくのが常に間違いとは限りません(シグナルがないよりは少しでもあるほうがよい場合もあります)が、多くの場合、データ収集の問題を示しているため、フラグを付ける価値があります。

def find_near_constant(df, threshold=0.98):
    return [
        {"feature": c, "top_value_freq": float(df[c].value_counts(normalize=True).iloc[0])}
        for c in df.columns
        if df[c].value_counts(normalize=True).iloc[0] > threshold
    ]
5. 冗長な特徴量の検出

相互相関が 0.95 を超える特徴量は、同じ情報を持っています。 各ペアから一方を削除して、多重共線性を軽減します(線形モデルには 木モデルより大きな影響を与えますが、計算リソースの無駄にもなります)。

def find_redundant_pairs(df, numeric_cols, threshold=0.95):
    corr = df[numeric_cols].corr().abs()
    out = []
    for i, c1 in enumerate(numeric_cols):
        for c2 in numeric_cols[i + 1:]:
            if float(corr.loc[c1, c2]) > threshold:
                out.append({"pair": [c1, c2], "pearson": float(corr.loc[c1, c2])})
    return out

視覚的なチェック(必ず出力に含める)

以下の 6 つのプロットを合わせて確認すれば、「このデータには何が含まれているのか?」が 30 秒でわかります。

  1. 欠損データの棒グラフ — 欠損率の高い順に並べます
  2. 数値分布のグリッド — 歪度を注記したヒストグラムです
  3. カテゴリのカーディナリティの棒グラフ — ユニーク値が 50 個を超えるものを赤い棒で示します
  4. 相関ヒートマップ — 特徴量 × ターゲットのピアソン相関を示し、ターゲット列には実際の数値を注記します
  5. 相互情報量とピアソン相関の並列棒グラフ — ピアソン相関では見逃される非線形のシグナルを明らかにします
  6. 外れ値の箱ひげ図 — 数値列ごとに、IQR に基づく外れ値の数を示します

プロットと並べて findings.json ファイルを出力します。各検出結果には、特徴量名、検出の根拠となった指標、推奨アクションを含めます。 実際に対応する対象はこのリストであり、プロットは根拠資料です。

ターゲットの型推定

モデリングを始める前に、ヒューリスティックに基づいてターゲットの型を推定します。

def infer_target_type(y):
    if y.dtype.kind in "biu":  # bool / int
        n_unique = y.nunique()
        if n_unique == 2:
            return "binary"
        if n_unique <= 20:
            return "multiclass"
        return "regression"
    if y.dtype.kind == "f":
        return "regression"
    return "categorical"

これにより、次に呼び出す下流のスキルが決まります。

  • binary → 二値分類スキル
  • multiclass → 多クラス分類スキル
  • regression → 回帰スキル
  • categorical(明確なターゲットがない場合) → 教師なし学習スキル

よくある落とし穴

  1. EDA をまったく行わない。「そのまま XGBoost にかければいい。」これが、ターゲットリークや「テスト精度は 99%なのに本番環境では動かない」という事態を招きます。
  2. **ピアソン相関だけを使う。**サイン関数、二次関数、カテゴリの関係を見逃します。必ず相互情報量と併用します。
  3. **データ所有者に確認せず「リークしている」特徴量を削除する。**その特徴量が正当な場合もあります(上流モデルの予測など)。削除する前に確認します。
  4. **カーディナリティの高いカテゴリ変数に OneHotEncoding を適用する。**特徴量数が爆発的に増え、モデルがノイズに埋もれ、学習が遅くなります。ターゲットエンコーディング、頻度エンコーディングを使うか、列を削除します。
  5. **重複を確認しない。**重複行が 50%あるデータセットでは、重複行が学習データとテストデータの両方に入ると、テスト指標が水増しされます。
  6. **よく考えずに欠損値を補完する。**MCAR なら中央値で補完しますが、MAR/MNAR の場合は欠損そのものをモデル化する必要があるかもしれません。欠損パターンには必ずフラグを立て、気づかれないまま補完しないでください。
  7. **EDA レポートを一時的なものとして扱う。**検出結果の JSON とプロットを MLflow(または使用中の実験トラッカー)に記録します。6 か月後にモデルが失敗したとき、データを最初にプロファイリングした時点の EDA レポートを確認できるようにしておきます。

実行例

demo.py(marimo ノートブック)を参照してください。意図的に問題を含めた合成の二値分類データセットを生成し、埋め込まれた 7 つの問題(ターゲットリーク、カーディナリティの高いカテゴリ、ほぼ定数の特徴量、30%の欠損データ、対数正規分布の歪み、2%の外れ値、冗長なペア)の検出方法を順に確認できます。ノートブックの最後には、EDA パイプラインが検出した内容をまとめた検出結果の表があります。この表が「次にどのモデルを学習すればよいか?」を判断するための入力になります。

EDA の後に行うこと

検出結果に基づいて、次のように判断します。

  • 削除:リークしている特徴量、ほぼ定数の特徴量、冗長なペアのうち一方
  • エンコード:カーディナリティの高いカテゴリ変数には、ターゲット/頻度/ハッシュエンコーディングを適用
  • 補完:欠損データ(数値には中央値、カテゴリには「missing」センチネル値)
  • 変換:歪んだ特徴量(対数、Box-Cox)、外れ値(ウィンズライジングまたはロバストスケーラー)
  • 次に:問題の種類に適したスキルを呼び出します(二値分類、回帰、多クラス分類など)

コメント