Top 5 This Week

関連記事

【医療統計版】解析を始める前に:データ辞書と作業の順序

- 本サイト運営者のサービスの紹介 -

研究データが届いた直後に群間差の検定や回帰モデルを試しても、同じ「999」が実測値なのか欠測コードなのかで計算結果は反対方向へ動き、列名から意味を推測して原データを直接直せば、後からどの値をなぜ変えたのか追えません。そのため、解析は手法の選択からではなく、研究目的と観測単位を確認し、変数の意味をデータ辞書に固定してから始まります。

解析の入口は研究目的と観測単位

「治療群と対照群で収縮期血圧の変化量を比べる」という目的なら、変化量が追跡時からベースラインを引いた値なのか、その逆なのかを先に確定します。符号の定義が反対なら、同じ数値でも治療群の改善を示す向きが反転するため、モデルを選ぶ前にアウトカムの意味を固定する必要があります。

その目的に続いて確認するのが、データの1行が何を表すかです。1行が1人なら群間比較へ進めますが、1人に複数時点の行があるデータを独立な600人として扱えば、同じ対象者内の相関を無視することになります。

この観測単位について、識別子が一意かどうかだけで判断するのは不十分です。同じ対象者に複数の検査、入院、測定時点が結び付く研究では、対象者表と繰り返し測定表を分け、それぞれの1行の意味と結合に使う識別子を定めます。

さらに、解析計画書とデータ辞書の対応も確認します。計画書で主要アウトカムを「12週時点」と定めても、辞書に来院日しかなければ許容する測定窓を決められないため、解析前に時点の選択規則と複数測定がある場合の優先順位を明文化します。

また、対象者の除外条件も変数として追跡できる形にします。適格基準を満たさない理由、同意撤回、重複登録などを一つの除外フラグへまとめるだけでは内訳を再確認できないため、元の理由を保持したまま解析対象フラグを導出します。

データ辞書が列名の推測を止める

データ辞書は、少なくとも変数の意味、研究上の役割、型、単位、許容値またはコード、欠測コード、測定時点、導出規則、解析上の扱いがそろうと、同じ列を別の人が別の意味で読むリスクを減らせます。

たとえばsbp_changeという名前だけでは、測定単位、差を取る向き、どの時点同士の差かが残ります。そこで「追跡時収縮期血圧-ベースライン収縮期血圧、単位mmHg、999は欠測」と記録すれば、負の値を異常値として消す誤りも、999を実測値として平均へ入れる誤りも避けやすくなります。

また、治療群を0、対照群を1と符号化したデータと、その逆のデータは外見だけでは区別できません。コード表を解析者の記憶やメールに残すのではなく辞書に含めると、群間差の向きと基準群を解析コードから追跡できます。

さらに、変数の由来も辞書の一部です。電子カルテから直接得た値、複数項目から導出した値、判定委員会が確定した値では更新経路が異なるため、取得元、導出式、確定日を残すと、同じ変数名でも版によって内容が変わる問題を追跡できます。

加えて、単位は変数名とは別に固定します。体重がkgかlbか、検査値が施設ごとの単位から換算済みかが不明なデータでは、範囲内に見える値でも誤った尺度が混ざるため、単位と換算規則を辞書に記録して解析用データで統一します。

原データと解析用データを分ける

BromanとWoo(2018)は、1セルに1つの値を置くデータ、一貫した欠測表現、データ辞書の作成を勧めています。この形は見た目を整えるためではなく、同じ規則をコードで繰り返し適用できるようにするための土台となるためです。

その土台を保つには、受領した原データを読み取り専用の基準として残し、辞書に基づく変換から解析用データを生成します。セルの値を直接上書きすると、変更前の値、変更理由、変更者が切り離され、結果を再生成する経路が失われます。

一方、コードによる変換なら、999を欠測へ置き換えたことも、測定時点を選んだことも記録として残ります。Peng(2011)が計算過程の再現可能性を科学的主張の最低限の基準に位置づけたように、原データ、辞書、変換コード、解析用データ、結果を分ける構造が結果の検証を支えます。

そのため、解析結果のファイルを手で修正せず、解析用データから表と図まで一続きに生成し、数値の訂正が必要になった時も、上流の辞書または変換規則を直して再実行すれば、本文だけ古い値のまま残る事態を防ぐことにも繋がります。

また、追跡調査の追加や照会回答によって原記録が更新された場合、どの時点のデータから結果を作ったかが分からなければ同じコードでも数値を再現できないため、解析用データには作成日と入力データの版を対応させます。

異常値は検出から処置へ飛ばさない

範囲外の値を見つけた時、直ちに削除したり上限値へ置き換えたりする進め方は適切ではありません。Van den Broeckら(2005)が示す検出、診断、処置の区別に沿えば、値の異常を見つけた後に発生原因を調べ、その根拠に応じて扱いを決められます。

その区別が必要なのは、同じ999でも意味が決まっていない段階では、入力誤り、機器の値、欠測コードのどれか判断できないためです。辞書やデータ収集票で欠測コードと照合できた場合に欠測へ変換し、確認できない値は照会対象として残す方が、根拠のない自動修正より追跡可能です。

さらに、許容範囲内の値にも矛盾は残ります。退院日が入院日より前、追跡時点の測定が登録日前、同じ識別子に異なる割付群が記録されている、といった関係は単独の最小値と最大値では見つかりません。

こうした矛盾の検査は、値の分布、変数同士の関係、時系列の順序という複数の層で考えます。検出件数、診断結果、採用した処置、根拠を残しておけば、除外後の人数がなぜ減ったのかを結果から原記録までたどれます。

群間差の向きまで辞書で固定する

治療群を$g=1$、対照群を$g=0$とし、対象者$i$の収縮期血圧変化量を$Y_i$とします。治療群から対照群を引く群間差は、次の式で定義できます。

$$
\widehat{\Delta}=\frac{1}{n_1}\sum_{i:g_i=1}Y_i-\frac{1}{n_0}\sum_{i:g_i=0}Y_i. \tag{1}
$$

式(1)の$\widehat{\Delta}$は標本で求めた群平均の差、$n_1$と$n_0$は各群で解析に使える対象者数です。ここでは$Y_i$を追跡時からベースラインを引いた値と定めたため、負の$\widehat{\Delta}$は治療群で低下が大きい向きを表します。

この符号を「改善」とだけ記録すると、アウトカムが有害事象数や生活の質へ変わった時に同じ解釈を流用できません。変数の算出式と群間差の引き算の順序を明示して初めて、数値の正負と研究目的を対応させられます。

欠測コード999で結果が反転する例

各群300例、合計600例の収縮期血圧変化量をランダムに生成し、生成時の治療効果を−5.0mmHg、標準偏差を8.0mmHgとしました。欠測コード999は対照群6例、治療群30例に置き、全体では36例、6.0%です。

その999を数値として平均へ入れると、対照群平均は19.73mmHg、治療群平均は95.08mmHgとなり、式(1)の群間差は75.35mmHgでした。実測値の範囲から離れたコードが治療群に多いため、このデータでは生成時に置いた効果と反対の正方向へ結果が動いています。

そこで辞書に従って999を欠測へ変換すると、対照群平均は−0.26mmHg、治療群平均は−5.36mmHg、群間差は−5.10mmHgでした。線形モデルで求めた同じ差の95%信頼区間は−6.40〜−3.80mmHgであり、これはデータ辞書の役割を示すランダム生成例で、実在する治療効果を表しません。

ここでは999が欠測コードだと既知なので変換できますが、欠測が生じた仕組みによる偏りや欠測値を除いた解析の妥当性は別に検討する必要があるため、この反転から「欠測処理をすれば常に正しい値へ戻る」と一般化することはできません。

Rで処理前後を再現する

同じ設定のデータをbase Rとstatsパッケージだけで用意し、辞書に基づく変換後の群平均差を線形モデルの係数でも照合しました。掲載する部分では、999を欠測へ変換する規則と、比較に必要な計算を残しています。

set.seed(42)
participants <- 600L
treatment <- rep(c(0L, 1L), each = participants / 2L)
sbp_change_complete <- rnorm(participants, mean = -5 * treatment, sd = 8)
sentinel_rows <- c(sample(which(treatment == 1L), 30L),
                   sample(which(treatment == 0L), 6L))
sbp_change_recorded <- sbp_change_complete
sbp_change_recorded[sentinel_rows] <- 999
sbp_change_clean <- sbp_change_recorded
sbp_change_clean[sbp_change_clean == 999] <- NA_real_
clean_model <- lm(sbp_change_clean ~ treatment)
c(coef(clean_model)["treatment"], confint(clean_model, "treatment"))
#> treatment  -5.100884
#> 2.5 %      -6.399974
#> 97.5 %     -3.801794

出力の最初の値は治療群平均から対照群平均を引いた推定値で、続く2値が95%信頼区間です。読み違えやすいのは、負の符号だけを見て治療の優劣を断定する点であり、ここでは変化量と群間差の定義を先に読んで初めて方向を解釈できます。

par(mfrow = c(1, 2))
boxplot(sbp_change_recorded ~ treatment,
        names = c("Control", "Treatment"), ylab = "SBP change (mmHg)",
        main = "Before recoding 999")
boxplot(sbp_change_clean ~ treatment,
        names = c("Control", "Treatment"), ylab = "SBP change (mmHg)",
        main = "After recoding 999 as missing")
abline(h = 0, lty = 2, col = "gray50")
欠測コード999の処理前には両群の箱ひげ図が大きく押し上げられ、欠測への変換後には治療群の収縮期血圧変化量が対照群より低く見える比較図
図1 欠測コード999を数値として扱った左図では実測部分が圧縮されますが、欠測へ変換した右図では群ごとの分布を読めます。左右で縦軸の範囲が異なるため、箱の高さそのものではなく999が分布表示と群平均を支配する様子を確認します。

図では処理前の縦軸が999に引っ張られ、実測値の分布が下端へ押しつぶされています。これに対して処理後は実測部分の広がりを確認できますが、図だけで999を欠測と決めるのではなく、辞書との照合が処置の根拠です。

解析開始時に残す判断

解析を始める時に重要なのは、最初から複雑なモデルを選ぶことではありません。研究目的に対応するアウトカム、1行の観測単位、群と時点の定義、欠測コードを辞書で確定し、原データを残したまま解析用データを生成することです。

その順序なら、異常値を見つけた段階で削除へ飛ばず、原因の診断と処置の根拠を記録できます。さらに、解析用データ、表、図を同じコードから生成することで、数値が変わった時も変更箇所を上流へ戻って確認することができます。

参考文献

  1. Broman KW, Woo KH. Data Organization in Spreadsheets. The American Statistician. 2018;72(1):2-10.
  2. Van den Broeck J, Cunningham SA, Eeckels R, Herbst K. Data Cleaning: Detecting, Diagnosing, and Editing Data Abnormalities. PLoS Medicine. 2005;2(10):e267.
  3. Rashid SM, McCusker JP, Pinheiro P, et al. The Semantic Data Dictionary—An Approach for Describing and Annotating Data. Data Intelligence. 2020;2(4):443-486.
  4. Wilkinson MD, Dumontier M, Aalbersberg IJJ, et al. The FAIR Guiding Principles for Scientific Data Management and Stewardship. Scientific Data. 2016;3:160018.
  5. Peng RD. Reproducible Research in Computational Science. Science. 2011;334(6060):1226-1227.

Popular Articles