臨床データは、そのまま機械学習に渡せる形ではありません。 FIM、歩行速度、握力、施設 ID、疾患名、薬剤名には、 外れ値、表記揺れ、単位差、尺度差が含まれます。 これらを機械的に処理すると、 臨床的に重要な症例を失うことがあります。 一方で、放置するとモデルが不安定になります。
この記事では、外れ値の見つけ方、カテゴリ変数のエンコード、 標準化の使い分けを整理します。 基本は、数値を整える前に臨床的意味を確認することです。 そのうえで、Scaler や Encoder を Pipeline に入れます。 基本用語は 02·01 説明変数と目的変数、 実装上の注意は 09·02 データリーケージとは何かも参照してください。
// 01 · LEARN OUTCOMESこの記事でわかること
- 外れ値を統計的基準と臨床的基準で確認できます。
- One-Hot、Ordinal、Target、Frequency Encoding の違いを説明できます。
- StandardScaler、MinMaxScaler、RobustScaler などを使い分けられます。
- Scaler と Encoder を Pipeline 内で fit する理由を説明できます。
// 02 · CONCLUSION最初に結論
// 03 · FIGURE前処理で数値を整える流れ
標準化とは、変数の尺度をそろえる操作です。 年齢は 0〜100 程度、FIM 合計点は 18〜126、 歩行速度は 0〜2 m/s 程度です。 そのまま距離ベースのモデルに入れると、 尺度の大きい変数が強く効くことがあります。
ただし、標準化は数値を見やすくする操作ではありません。 モデルが扱いやすい表現に変える操作です。 外れ値を含む変数に StandardScaler を使うと、 平均と標準偏差が外れ値に引っ張られます。 その場合、RobustScaler などを検討します。
カテゴリ変数では、まず順序の有無を確認します。 性別、疾患名、施設 ID には自然な順序がありません。 介助量の段階や重症度分類には順序があります。 順序のないカテゴリを 0, 1, 2 と置くと、 モデルが架空の大小関係を学ぶ場合があります。
// 04 · CLINICALリハ研究で起きやすい前処理の場面
FIM 合計点は 18〜126 点の範囲です。 そのため、7 点未満の値は通常の範囲外です。 まず入力ミス、合計方法、欠損コードを確認します。 ただし、低値だから機械的に削除するのではありません。 評価尺度の定義とデータ辞書を照合します。
施設 ID は、回復期病棟の方針、測定機器、 患者背景の違いを含むことがあります。 One-Hot Encoding では列数が増えます。 Target Encoding は列数を抑えられますが、 目的変数の情報を使うためリーケージに注意します。 fold 内で fit する設計が前提になります。
歩行速度 5 m/s は、臨床データでは異常に高い値です。 単位の誤り、センサー異常、切り出しミスを確認します。 明らかな機器エラーなら除外候補になります。 一方で、上限値に丸める Winsorize も選択肢です。 どの扱いにしたかを Methods に残します。
電子カルテの薬剤名は表記揺れが起きます。 同じ薬剤でも、略称、商品名、一般名が混在します。 まず辞書で正規化します。 その後、出現頻度を使う Frequency Encoding や、 薬効分類への集約を検討します。
// 05 · THEORY外れ値・エンコード・標準化の考え方
外れ値検出には、統計的な基準があります。 箱ひげ図、Z-score、IQR、Mahalanobis 距離などです。 ただし、外れ値検出は診断ではありません[1]。 「見つける」ことと「除外する」ことは分けます。
Z-score は、平均から何標準偏差離れているかを見ます。 分布が大きく歪む変数では、過度に反応することがあります。 IQR は四分位範囲を用いるため、 外れ値の影響を受けにくい方法です。 Mahalanobis 距離は、多変量の外れ方を見ます。
Z-score:
z = (x - mean) / sd
IQR rule:
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
IQR = Q3 - Q1
Mahalanobis distance:
D2 = (x - mean_vector)' S_inverse (x - mean_vector)
外れ値への対応には、複数の選択肢があります。 明らかな入力ミスなら修正または除外を検討します。 臨床的にあり得る極端値なら残します。 分布の歪みが問題なら log 変換や平方根変換を使います。 上下限に丸める Winsorize も選択肢です。
カテゴリ変数は、数値への置き換えが必要です。 One-Hot Encoding は、カテゴリごとに 0/1 列を作ります。 順序のない少数カテゴリで扱いやすい方法です。 ただし、施設 ID のようにカテゴリ数が多いと、 列数が増え、過学習しやすくなります。
Ordinal Encoding は、順序のあるカテゴリに向きます。 たとえば「自立、監視、軽介助、中等度介助」などです。 ただし、段階間の距離が等しいとは限りません。 数値化した後も、臨床的な意味を確認します。
Target Encoding:
encoded(category c) = mean(y | category = c)
Smoothed Target Encoding:
encoded(c) = (n_c * mean_c + alpha * global_mean) / (n_c + alpha)
Leakage risk:
If mean_c is calculated using the validation fold,
information from y_validation enters X_validation.
Target Encoding は、カテゴリごとの目的変数平均を使います[5]。 施設 ID のような高カードカテゴリで便利です。 しかし、目的変数を使うため注意が必要です。 validation fold の y を使って変換すると、 評価データの答えを前処理に混ぜることになります。
標準化では、代表的に以下を使います。 StandardScaler は平均 0、標準偏差 1 に変換します。 MinMaxScaler は範囲を 0〜1 にそろえます。 RobustScaler は中央値と IQR を使います。 QuantileTransformer は分布の形を変えます。 PowerTransformer は歪んだ分布を緩和します。
StandardScaler:
z = (x - mu) / sigma
MinMaxScaler:
x_scaled = (x - x_min) / (x_max - x_min)
RobustScaler:
x_scaled = (x - median) / IQR
標準化の選択では、分布の形も見ます。 FIM 合計点のように上限と下限が決まる尺度と、 訓練量のように右に裾を引く尺度では、 同じ変換が合うとは限りません。 PowerTransformer や QuantileTransformer は、 分布を大きく変えるため、解釈性も確認します。 変換後の係数や重要度を、元の単位に戻して説明できるかも大切です。
どのモデルで標準化が重要かも整理します。 線形回帰、ロジスティック回帰、kNN、SVM、 ニューラルネットワークでは尺度の影響が出ます。 特に正則化を使う線形モデルでは、 標準化しないと係数の比較が難しくなります。
一方で、Random Forest や勾配ブースティングなどの木系モデルは、 分割のしきい値で学習します。 そのため、単調な尺度変換の影響は小さいことが多いです。 ただし、前処理の一貫性や他モデルとの比較のため、 Pipeline の中で設計を明示しておくことは有用です。
// 06 · IMPLEMENTATIONPipeline で安全に前処理する
実装では、前処理を pandas で全データに当ててから train / test に分ける流れを避けます。 scaler、imputer、encoder は、 すべて Pipeline の中で fit します。 これにより、交差検証の各 fold でも、 train fold 内だけで前処理が学習されます。
# 教育用の仮想データ example_rehab_dataset.csv を想定します。
# 実データでは、個人情報保護、倫理審査、施設ルール、
# データ利用規約を確認したうえで解析環境に置いてください。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import StratifiedKFold, cross_val_score, train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler, RobustScaler, QuantileTransformer
# 1. データ読み込み
df = pd.read_csv("example_rehab_dataset.csv")
# 2. 予測時点を確認して列を選ぶ
# 例: 入院時に歩行自立を予測する設定
# 退院時 FIM や退院後追跡データは説明変数から外します。
target = "walk_independent_discharge"
numeric_cols = [
"age", "fim_total_admission", "sias_lower_admission",
"grip_strength_admission", "gait_speed_admission",
]
categorical_cols = ["sex", "stroke_type", "facility_id"]
X = df[numeric_cols + categorical_cols].copy()
y = df[target].astype(int)
# 3. 全体像の確認は記述統計に留める
print(df[numeric_cols].describe())
print(df[categorical_cols].nunique())
print(df.isna().mean().sort_values(ascending=False).head(10))
# 4. 外れ値候補を臨床的範囲で確認する
clinical_flags = pd.DataFrame(index=df.index)
clinical_flags["fim_range_error"] = ~df["fim_total_admission"].between(18, 126)
clinical_flags["gait_speed_high"] = df["gait_speed_admission"] > 3.0
clinical_flags["age_high"] = df["age"] > 105
print(clinical_flags.sum())
# 5. 箱ひげ図は探索用に使う
for col in numeric_cols:
ax = df.boxplot(column=col)
ax.set_title(col)
plt.savefig(f"boxplot_{col}.png", dpi=150, bbox_inches="tight")
plt.close()
# 6. NG 例: 全データで scaler を fit してから split しない
# scaler = StandardScaler()
# X_scaled = scaler.fit_transform(X[numeric_cols]) # validation 情報が混入
# X_train, X_test, y_train, y_test = train_test_split(X_scaled, y)
# 7. カテゴリ列は One-Hot Encoding にする
categorical_onehot = Pipeline(steps=[
("imputer", SimpleImputer(strategy="most_frequent")),
("onehot", OneHotEncoder(handle_unknown="ignore")),
])
# 8. 数値 scaler を差し替えながら比較する関数
def build_pipe(scaler):
numeric_pipe = Pipeline(steps=[
("imputer", SimpleImputer(strategy="median")),
("scaler", scaler),
])
preprocess = ColumnTransformer(transformers=[
("num", numeric_pipe, numeric_cols),
("cat", categorical_onehot, categorical_cols),
])
pipe = Pipeline(steps=[
("preprocess", preprocess),
("model", LogisticRegression(max_iter=2000, class_weight="balanced")),
])
return pipe
# 9. train / test 分割後、fit は train 側だけで行う
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
pipe_standard = build_pipe(StandardScaler())
pipe_standard.fit(X_train, y_train)
prob = pipe_standard.predict_proba(X_test)[:, 1]
print("test_auc", roc_auc_score(y_test, prob))
# 10. CV では fold ごとに preprocess が fit される
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(pipe_standard, X, y, cv=cv, scoring="roc_auc")
print("standard_cv_auc_mean", scores.mean())
print("standard_cv_auc_sd", scores.std())
# 11. RobustScaler と QuantileTransformer を同じ構造で比較する
scaler_candidates = {
"standard": StandardScaler(),
"robust": RobustScaler(),
"quantile_normal": QuantileTransformer(
output_distribution="normal", random_state=42
),
}
for name, scaler in scaler_candidates.items():
candidate_pipe = build_pipe(scaler)
auc = cross_val_score(candidate_pipe, X, y, cv=cv, scoring="roc_auc")
print(name, auc.mean(), auc.std())
# 12. Target Encoding を使う場合の注意
# 目的変数を使う変換は、validation fold の y を使わない設計にします。
# 専用ライブラリを使う場合も、CV 内 fit になっているか確認します。
# 13. 同一患者の複数評価がある場合
# patient_id が複数行に出る設計では、GroupKFold を検討します。
# 同じ患者が train と validation に分かれないようにします。
この例では、数値列とカテゴリ列を分けています。 数値列には中央値補完と標準化を行います。 カテゴリ列には最頻値補完と One-Hot Encoding を行います。 どちらも ColumnTransformer に入れてから、 LogisticRegression と Pipeline でつないでいます。
RobustScaler や QuantileTransformer の比較も、 同じ Pipeline 構造で行います。 重要なのは、scaler だけを先に全データで fit しないことです[3]。 外れ値処理、カテゴリ変換、標準化は、 モデル評価と一体で設計します。
Target Encoding や Frequency Encoding は、 高カードカテゴリを扱うときの候補になります。 ただし、薬剤名や施設 ID は、 患者背景や診療体制を強く反映します。 そのため、単なる圧縮手法として扱わず、 何を表す変数なのかを Methods で説明します。 多施設研究では、施設を調整因子として扱うのか、 外部妥当性を確認する単位として扱うのかも整理します。
// 07 · MYTHSよくある誤解
- 誤解 1:外れ値は全部除外した方がよい
- 外れ値には、入力ミスと臨床的に重要な極端例があります。 脳卒中の重症例、超高齢者、重度低 FIM 例は、 研究対象として重要な場合があります。 除外は、定義と理由を記録してから検討します。
- 誤解 2:Target Encoding はリーケージしない
- Target Encoding は目的変数を使います。 validation fold の y を使ってカテゴリ平均を計算すると、 評価データの答えを説明変数に混ぜることになります。 out-of-fold で計算する設計が必要です。
- 誤解 3:すべての変数で標準化が必要
- 標準化の必要性はモデルに依存します。 線形モデル、kNN、SVM、NN では重要です。 Random Forest や勾配ブースティングでは、 多くの場合、標準化の影響は限定的です。
- 誤解 4:One-Hot Encoding ならカテゴリ変数は安全
- カテゴリ数が多いと列数が増えます。 多施設データや薬剤名では、次元増加により 過学習しやすくなることがあります。 Frequency Encoding や集約カテゴリも候補になります。
// 08 · WRITING論文 Methods で書くこと
前処理は、論文では短く書かれがちです。 しかし、外れ値、カテゴリ変数、標準化は、 性能評価と再現性に直結します。 TRIPOD+AI でも、データ処理と予測モデルの再現性は 重要な報告項目として扱われます[6]。
- 外れ値の定義を記載します。例: IQR、臨床的範囲、単位確認。
- 除外、Winsorize、変換、外れ値フラグの扱いを記載します。
- カテゴリ変数のエンコード方法を記載します。
- 高カードカテゴリの扱いを記載します。
- 標準化の方法と対象モデルを記載します。
- Scaler / Encoder を train fold 内で fit したことを記載します。
- 感度分析を行った場合は、その条件を記載します。
査読では、外れ値の扱いがよく問われます。 特に、除外後に性能が改善した場合は注意が必要です。 入力ミスを除いたのか、重症例を除いたのかで、 研究の意味が変わります。 除外例の数と理由を示すと、解釈しやすくなります。
Target Encoding を使った場合は、 out-of-fold で算出したことを明記します。 全データでカテゴリ平均を計算すると、 データリーケージを疑われます。 詳細は 09·02 データリーケージとは何かと、 02·06 データリーケージを防ぐ前処理で扱います。
標準化の有無も、モデルごとに説明します。 線形回帰や ロジスティック回帰では、 正則化や係数解釈に関係します。 k近傍法では、 距離計算そのものに影響します。
// 09 · CHECKLIST前処理前の確認リスト
- 01各数値列について、単位と臨床的にあり得る範囲を確認した。
- 02箱ひげ図、ヒストグラム、IQR で外れ値候補を確認した。
- 03外れ値を入力ミス、測定誤差、臨床的極端例に分けて記録した。
- 04カテゴリ変数について、順序の有無を確認した。
- 05高カードカテゴリの列数増加を確認した。
- 06Target Encoding を使う場合、fold 内 fit の設計にした。
- 07モデルに応じて、標準化の必要性を確認した。
- 08Scaler と Encoder を Pipeline / ColumnTransformer に入れた。
// 10 · QUIZ理解度チェック
-
Q1FIM 合計点に 7 点という値がありました。最初に行うこととして適切なのはどれですか。
- 低値なので除外する
- 外れ値として平均値に置き換える
- 尺度の範囲、入力ミス、欠損コードを確認する
- 標準化すれば問題ない
SHOW ANSWER
C. 外れ値候補は、まず定義と臨床的意味を確認します。 -
Q2Target Encoding で最も注意する点はどれですか。
- カテゴリ数が 2 つだと使えない
- 目的変数を使うため、fold 内で計算する
- 数値列にしか使えない
- 木系モデルでは必ず必要になる
SHOW ANSWER
B. validation の y を変換に使うとリーケージします。 -
Q3StandardScaler が特に重要になりやすいモデルはどれですか。
- kNN
- Random Forest
- 決定木単体
- ルールベース分類
SHOW ANSWER
A. kNN は距離に基づくため、尺度差の影響を受けます。 -
Q4歩行速度 5 m/s が見つかった場合の説明として適切なのはどれですか。
- 外れ値なので理由に関係なく削除する
- まず単位、測定機器、切り出し方法を確認する
- 平均値で補完する
- One-Hot Encoding する
SHOW ANSWER
B. 外れ値候補は、機器エラーか臨床的値かを分けて考えます。
// REF参考文献
- Kuhn M, Johnson K. Feature Engineering and Selection: A Practical Approach for Predictive Models. CRC Press, 2019.
- Harrell FE Jr. Regression Modeling Strategies. 2nd ed. Springer, 2015.
- Pedregosa F, Varoquaux G, Gramfort A, Michel V, Thirion B, Grisel O, et al. Scikit-learn: Machine learning in Python. Journal of Machine Learning Research 2011;12:2825-2830.
- Hastie T, Tibshirani R, Friedman J. The Elements of Statistical Learning. 2nd ed. Springer, 2009.
- Micci-Barreca D. A preprocessing scheme for high-cardinality categorical attributes in classification and prediction problems. ACM SIGKDD Explorations Newsletter 2001;3(1):27-32.
- Collins GS, Moons KGM, Dhiman P, Riley RD, Beam AL, Van Calster B, et al. TRIPOD+AI statement: updated guidance for reporting clinical prediction models that use regression or machine learning methods. BMJ 2024;385:e078378.