欠損値の多重代入


13

特定の制約の下でデータセットの欠損値を置き換えるために代入を使用したいと思います。

たとえば、代入さx1れた変数が、他の2つの変数、たとえばx2との合計以上になるようにしますx3。またx30またはのいずれかに代入され>= 14たいx20またはのいずれかに代入されたい>= 16

複数の代入に対してSPSSでこれらの制約を定義しようとしましたが、SPSSでは最大値と最小値しか定義できません。SPSSでさらに制約を定義する方法はありますか、または、欠損値の代入のためにこのような制約を定義できるRパッケージを知っていますか?

私のデータは次のとおりです。

   x1 =c(21, 50, 31, 15, 36, 82, 14, 14, 19, 18, 16, 36, 583, NA,NA,NA, 50, 52, 26, 24)
   x2 = c(0, NA, 18,0, 19, 0, NA, 0, 0, 0, 0, 0, 0,NA,NA, NA, 22, NA, 0, 0)
   x3 = c(0, 0, 0, 0, 0, 54, 0 ,0, 0, 0, 0, 0, 0, NA, NA, NA, NA, 0, 0, 0)
   dat=data.frame(x1=x1, x2=x2, x3=x3)
   > dat
       x1 x2 x3
   1   21  0  0
   2   50 NA  0
   3   31 18  0
   4   15  0  0
   5   36 19  0
   6   82  0 54
   7   14 NA  0
   8   14  0  0
   9   19  0  0
   10  18  0  0
   11  16  0  0
   12  36  0  0
   13 583  0  0
   14  NA NA NA
   15  NA NA NA
   16  NA NA NA
   17  50 22 NA
   18  52 NA  0
   19  26  0  0
   20  24  0  0

値を含むために変更0 or 16 or >= 16しました。それがあなたの意味を台無しにしないことを願っています。同じ0 or >= 16>=16160 or 14 or >= 14
アレクシス14年

回答:


16

1つの解決策は、miceパッケージ用に独自のカスタム代入関数を作成することです。パッケージはこのために準備されており、セットアップは驚くほど簡単です。

まず、提案されたとおりにデータをセットアップします。

dat=data.frame(x1=c(21, 50, 31, 15, 36, 82, 14, 14, 19, 18, 16, 36, 583, NA,NA,NA, 50, 52, 26, 24), 
               x2=c(0, NA, 18,0, 19, 0, NA, 0, 0, 0, 0, 0, 0,NA,NA, NA, 22, NA, 0, 0), 
               x3=c(0, 0, 0, 0, 0, 54, 0 ,0, 0, 0, 0, 0, 0, NA, NA, NA, NA, 0, 0, 0))

次に、miceパッケージをロードし、デフォルトで選択するメソッドを確認します。

library(mice)
# Do a non-imputation
imp_base <- mice(dat, m=0, maxit = 0)

# Find the methods that mice chooses
imp_base$method
# Returns: "pmm" "pmm" "pmm"

# Look at the imputation matrix
imp_base$predictorMatrix
# Returns:
#   x1 x2 x3
#x1  0  1  1
#x2  1  0  1
#x3  1  1  0

予測平均マッチングpmm略-おそらく連続変数を代入するための最も一般的な代入アルゴリズムです。回帰モデルを使用して予測値を計算し、予測値に最も近い5つの要素を選択します(ユークリッド距離による))を選択します。これらの選択された要素はドナープールと呼ばれ、最終値はこのドナープールからランダムに選択されます。

予測マトリックスから、メソッドは制限に関係する渡された変数を取得することがわかります。行がターゲット変数であり、列が予測変数であることに注意してください。x1のx3列に1がなかった場合、これをマトリックスに追加する必要があります。imp_base$predictorMatrix["x1","x3"] <- 1

さて、面白い方法として、代入メソッドを生成します。ここでは、基準を満たさない場合はすべての値を破棄する、かなり粗雑な方法を選択しました。これにより、ループ時間が長くなる可能性があり、有効な代入を保持し、残りの代入のみを再実行する方が効率的である可能性がありますが、少し調整が必要になります。

# Generate our custom methods
mice.impute.pmm_x1 <- 
  function (y, ry, x, donors = 5, type = 1, ridge = 1e-05, version = "", 
            ...) 
  {
    max_sum <- sum(max(x[,"x2"], na.rm=TRUE),
                   max(x[,"x3"], na.rm=TRUE))
    repeat{
      vals <- mice.impute.pmm(y, ry, x, donors = 5, type = 1, ridge = 1e-05,
                              version = "", ...)
      if (all(vals < max_sum)){
        break
      }
    }
    return(vals)
  }

mice.impute.pmm_x2 <- 
  function (y, ry, x, donors = 5, type = 1, ridge = 1e-05, version = "", 
            ...) 
  {
    repeat{
      vals <- mice.impute.pmm(y, ry, x, donors = 5, type = 1, ridge = 1e-05,
                              version = "", ...)
      if (all(vals == 0 | vals >= 14)){
        break
      }
    }
    return(vals)
  }

mice.impute.pmm_x3 <- 
  function (y, ry, x, donors = 5, type = 1, ridge = 1e-05, version = "", 
            ...) 
  {
    repeat{
      vals <- mice.impute.pmm(y, ry, x, donors = 5, type = 1, ridge = 1e-05,
                              version = "", ...)
      if (all(vals == 0 | vals >= 16)){
        break
      }
    }
    return(vals)
  }

メソッドの定義が完了したら、前のメソッドを単純に変更します。単一の変数のみを変更したい場合は、単に使用できますimp_base$method["x2"] <- "pmm_x2"が、この例ではすべてを変更します(命名は不要です):

imp_base$method <- c(x1 = "pmm_x1", x2 = "pmm_x2", x3 = "pmm_x3")

# The predictor matrix is not really necessary for this example
# but I use it just to illustrate in case you would like to 
# modify it
imp_ds <- 
  mice(dat, 
       method = imp_base$method, 
       predictorMatrix = imp_base$predictorMatrix)

次に、3番目の帰属データセットを見てみましょう。

> complete(imp_ds, action = 3)
    x1 x2 x3
1   21  0  0
2   50 19  0
3   31 18  0
4   15  0  0
5   36 19  0
6   82  0 54
7   14  0  0
8   14  0  0
9   19  0  0
10  18  0  0
11  16  0  0
12  36  0  0
13 583  0  0
14  50 22  0
15  52 19  0
16  14  0  0
17  50 22  0
18  52  0  0
19  26  0  0
20  24  0  0

わかりました、それは仕事をします。主流の機能に便乗し、意味のある制限を追加するだけで、このソリューションが気に入っています。

更新

コメントに記載されている@ t0x1nの厳密な制限を実施するために、ラッパー関数に次の機能を追加することができます。

  1. 前の部分的に成功した実行からのデータが破棄されないように、ループ中に有効な値を保存します
  2. 無限ループを回避するためのエスケープメカニズム
  3. 適切な一致を見つけることなくx回試行した後、ドナープールを膨張させます(これは主にpmmに適用されます)

これにより、ラッパー関数が少し複雑になります。

mice.impute.pmm_x1_adv <-   function (y, ry, 
                                      x, donors = 5, 
                                      type = 1, ridge = 1e-05, 
                                      version = "", ...) {
  # The mice:::remove.lindep may remove the parts required for
  # the test - in those cases we should escape the test
  if (!all(c("x2", "x3") %in% colnames(x))){
    warning("Could not enforce pmm_x1 due to missing column(s):",
            c("x2", "x3")[!c("x2", "x3") %in% colnames(x)])
    return(mice.impute.pmm(y, ry, x, donors = 5, type = 1, ridge = 1e-05,
                           version = "", ...))
  }

  # Select those missing
  max_vals <- rowSums(x[!ry, c("x2", "x3")])

  # We will keep saving the valid values in the valid_vals
  valid_vals <- rep(NA, length.out = sum(!ry))
  # We need a counter in order to avoid an eternal loop
  # and for inflating the donor pool if no match is found
  cntr <- 0
  repeat{
    # We should be prepared to increase the donor pool, otherwise
    # the criteria may become imposs
    donor_inflation <- floor(cntr/10)
    vals <- mice.impute.pmm(y, ry, x, 
                            donors = min(5 + donor_inflation, sum(ry)), 
                            type = 1, ridge = 1e-05,
                            version = "", ...)

    # Our criteria check
    correct <- vals < max_vals
    if (all(!is.na(valid_vals) |
              correct)){
      valid_vals[correct] <-
        vals[correct]
      break
    }else if (any(is.na(valid_vals) &
                    correct)){
      # Save the new valid values
      valid_vals[correct] <-
        vals[correct]
    }

    # An emergency exit to avoid endless loop
    cntr <- cntr + 1
    if (cntr > 200){
      warning("Could not completely enforce constraints for ",
              sum(is.na(valid_vals)),
              " out of ",
              length(valid_vals),
              " missing elements")
      if (all(is.na(valid_vals))){
        valid_vals <- vals
      }else{
        valid_vals[is.na(valid_vals)] <- 
          vals[is.na(valid_vals)]
      }
      break
    }
  }
  return(valid_vals)
}

これはそれほどうまく機能しないことに注意してください。これは、おそらく、提案されたデータセットがすべてのケースで制約を逃さずに失敗するためです。動作を開始する前に、ループの長さを400〜500に増やす必要があります。これは意図的なものではなく、あなたの帰属は実際のデータがどのように生成されるかを真似するべきだと思います。

最適化

引数ryには非欠損値が含まれており、適格な補完を見つけた要素を削除することでループを高速化できますが、内部関数に慣れていないため、これを控えました。

フルフィルに時間がかかる強力な制約がある場合、最も重要なことは代入を並列化することだと思います(CrossValidatedに関する私の答えをご覧ください)。ほとんどのコンピューターには4〜8コアのコンピューターがあり、Rはデフォルトでそのうちの1つのみを使用します。コアの数を2倍にすることで、時間を(ほぼ)半分にスライスできます。

代入時に欠落しているパラメーター

問題についてx2転嫁の時に行方不明であることを-マウスは、実際に欠損値を供給することはありませんx- data.frameマウスの方法は、開始時にいくつかのランダムな値で充填含みます。代入のチェーン部分は、この初期値からの影響を制限します。mice-function を見ると、代入呼び出しの前にこれを見つけることができます(mice:::sampler-function):

...
if (method[j] != "") {
  for (i in 1:m) {
    if (nmis[j] < nrow(data)) {
      if (is.null(data.init)) {
        imp[[j]][, i] <- mice.impute.sample(y, 
                                            ry, ...)
      }
      else {
        imp[[j]][, i] <- data.init[!ry, j]
      }
    }
    else imp[[j]][, i] <- rnorm(nrow(data))
  }
}
...

data.init供給することができるmice機能とmice.imput.sampleは基本サンプリング手順です。

訪問シーケンス

訪問順序が重要な場合、mice-functionが代入を実行する順序を指定できます。デフォルトはfromです1:ncol(data)が、を任意の値に設定できvisitSequenceます。


+1これは素晴らしいもので、まさに私が念頭に置いていたものです(フランクの答えに対する私のコメントを参照してください)。確かに、今のところ賞金の第一候補です。物事のカップルについての悩み私pmm_x1けれども:(1)のいずれかの可能性のある組み合わせの最大の和取るx2と、x3データセット全体からは、元の制約よりもはるかにストリンガーです。正しい事はそれをテストすることで行ごとにx1 < x2 + x3。もちろん、行が多いほど、そのような制約に準拠する可能性は低くなり(1つの悪い行がすべてを台無しにします)、ループが潜在的に長くなる可能性があります。
t0x1n 14年

(2)の両方の場合x1x2不足している、あなたは値転嫁もx1(のは、50を言わせて)制約が保持されているのが、一度x2彼らが壊れている帰属ます(のは、55であることを転嫁だとしましょう)。垂直ではなく「水平」に帰属させる方法はありますか?我々は、単一の行を転嫁する可能性がそのようにx1x2x3単純に再転嫁し、その特定の行は、制約の下で落ちるまで。それは十分に速いはずであり、それが終わったら次の行に移動できます。もちろん、MIがその性質上「垂直」である場合、私たちは運が悪いです。その場合、アレクサンドルが言及したアプローチでしょうか?
t0x1n 14年

クールなソリューション、+ 1!現在miceパッケージを使用しているため、特に便利です。共有してくれてありがとう。
アレクサンドルブレフ14年

1
@ t0x1nコメントに従って、より高度なラッパー関数を使用して回答を更新しました。さらに深く潜りたい場合は、ボンネットの下でその兄弟がdebug()どのように機能するかを確認するために、遊んでみることをお勧めしますmice.impute.pmm
マックスゴードン14年

1
@ t0x1n:推測-あなたの代入値を調べてください。それらが非現実的と思われる場合は、モデルの中心的ではないもののみを補完するために私のアプローチを選択できます。私の場合、フォローアップX線のないものは研究の中心にあり、補完は臨床的に妥当な値を提供しないため(骨折後に脚が長くなる)、除外することを選択しました。私はこれに完全に満足していませんが、合理的な妥協のようです。
マックスゴードン14年

8

私が見つけた最も近いものは、アメリアの以前の情報の包含です。ビネット、特に4.7.2の第4.7章を参照してください。

観測レベルの事前

多くの場合、研究者は、以前の研究、学術的コンセンサス、または個人的な経験に基づいて、欠落データ値に関する追加の事前情報を持っています。Ameliaはこの情報を組み込んで、大幅に改善された帰属を生成できます。Ameliaアルゴリズムを使用すると、ユーザーは、より一般的なモデルパラメーターの代わりに、個々の欠損データセルに関する有益なベイジアン事前分布を含めることができます。

事前確率の組み込みは、補完がモデルベースの補完と事前平均の加重平均であることが判明する基本的なベイジアン分析に従います。ここで、重みはデータと事前の相対的な強さの関数です。 、代入は以前の重みを小さくし、逆も同様です(Honaker and King、2010)。

個々の観測に関する事前分布は、欠落しているデータセルの分布に関するアナリストの信念を説明するものでなければなりません。これは、平均と標準偏差またはコンデンス間隔の形式を取ることができます。たとえば、1986年のタイのタリ率は約40%であることを知っているかもしれませんが、正確な値については不確実性があります。欠落しているデータセルの分布に関する以前の信念は、40を中心としており、標準偏差は以前の信念についての不確実性の量を反映しています。

事前分布を入力するには、4列または5列の事前分布行列を作成する必要があります。行列の各行は、1つの観測値または1つの変数の事前分布を表します。どの行でも、最初の列のエントリは観測値の行であり、2番目の列のエントリは観測値の列です。4列の事前行列では、3番目と4番目の列は欠損値の事前分布の平均と標準偏差です。

そのため、一般的にのように言うことはできませんがx1<x2+x3、データセットをループして、関連する各ケースに事前に観測レベルを追加できます。定数の境界も適用できます(x1、x2、x3を非負に設定するなど)。例えば:

priors = matrix(NA, nrow=0, ncol=5);
for (i in seq(1, length(data))) 
{
    x1 = data$x1[i];
    x2 = data$x2[i];
    x3 = data$x3[i];

    if (is.na(x1) && !is.na(x2) && !is.na(x3))
    {
        priors = rbind(priors, c(i, 1, 0, x2+x3, 0.999999))
    }
}

amelia(data, m=1, bound = rbind(c(1, 0, Inf), c(2, 0, Inf), c(3, 0, Inf)), pr = priors);

5

制約は、おそらく、複数の代入に一致する予測平均で実装する方が簡単です。これは、制約を満たす非欠損の制約変数を持つかなりの数の観測値があることを前提としています。R HmiscパッケージaregImpute関数でこれを実装することを考えています。1か月ほど後にもう一度確認してください。制約により、理想的な制約のないドナーからさらにドナーが押し出されるため、ドナーの観察が可能なターゲットからの最大距離を指定することが重要になります。


私もこれが欲しいです。最も基本的な変数間制約のみが必要ですx<y<z
t0x1n 14年

気分が悪くても私の無知は許してください。しかし、複数の代入手法には適切な分布から値を引き出すことが含まれているという印象を受けました。拒否サンプリングを使用するのは簡単なことではありませんか?たとえば、指定された制約(などx1<x2)が満たされるまで描画を続けますか?
t0x1n 14年

それがaregImpute、予測平均マッチングを使用してR 関数で行うことです。しかし、ドナーの観測値(予測のほぼ一致)が、明らかにドナー変数のセットの制約を満たさなければならない場合でも、代入されるターゲット観測の制約を満たさない場合はどうでしょうか。
フランクハレル14年

そのような場合、おそらく予測値を直接取りますか?それは、そのようなサンプルの回帰(PMMフェーズなし)のみに依存していますか?
t0x1n 14年

回帰代入は、対象の残りの記録と矛盾する代入値を見つける可能性がわずかに高くなります。ですから、これがPMMを避ける理由ではないと思います。
フランクハレル14年

4

Amelia(Amelia II)パッケージは現在、データ値の範囲の制約を指定するための最も包括的なサポートを持っていると思います。ただし、問題はAmelia、データが多変量正規であると想定していることです。

あなたの場合、多変量正規性の仮定が当てはまらない場合、連鎖方程式を介して複数の代入(MI)miceを実装するパッケージをチェックすることができます。このパッケージには、多変量正規性の仮定はありません。制約を指定するのに十分かもしれない関数もありますが、どの程度かはわかりません。関数が呼び出されます。これについては、ドキュメントhttp://cran.r-project.org/web/packages/mice/mice.pdfで読むことができます。その他の利点は、ユーザー定義の代入関数の指定とアルゴリズムの幅広い選択を可能にするという点での柔軟性です。以下は、MIの実行に関するチュートリアルです。squeeze()micemicehttp://www.ats.ucla.edu/stat/r/faq/R_pmm_mi.htm

私の知る限り、ハレル博士のHmiscパッケージは、同じ連鎖方程式予測平均マッチング)アプローチを使用して、非正規データをサポートしています(normpmmメソッドを除く)。おそらく、彼は上記の回答ごとに、既に制約仕様機能を実装しているでしょう。使用aregImpute()したことがないので、これ以上詳しくは言えません(とを使用Ameliaしましたmiceが、統計学の専門家ではありません。できる限り多くのことを学ぼうとしています)。

最後に、欠損値のあるデータを複数代入するためのアプローチ、方法、およびソフトウェアの概要が少し古くなっていますが、それでも興味深い概要を見つけることができます:http : //www.ncbi.nlm.nih.gov/pmc/articles / PMC1839993。MIに関するより新しい概要論文があると確信していますが、現時点ではそれだけです。これがいくらか役立つことを願っています。


1
このすてきなコメントは、観測されたすべてのデータがこれらの制約を満たす場合、欠損を実際に観測された値で置き換える予測平均マッチングが、ある種の制約をすでに組み込んでいると思います。これを考えている人に感謝します。私はまだ特別な制約を実装していませんaregImpute
フランクハレル14年

1
あなたが正しいです。私は、ドナーの観測がと一致している値を提供することを実現し、その他の変数ではなく、ターゲット変数に他の変数とします。
フランクハレル14年

1
アメリアが行った分布の仮定は別として、偶然、答えで示したよりも詳細に制約を指定することができましたか?問題squeezeは、その境界が一定であるため、のようなものを指定できないことですx1<x2。また、代入された結果ベクトルで呼び出されるようですが、手遅れだと思います。代入プロセス中に境界を考慮する必要があるように思えるので、事後調整よりも意味があります。
t0x1n 14年

1
@ t0x1n:残念ながら、データが多変量正規分布ではないことがテストで確認された直後Ameliamice、からに切り替えたため、で制約を指定する機会がありませんでした。しかし、最近、このトピック(MIメソッドとソフトウェア)の非常に素晴らしいプレゼンテーションスライドに出くわしました:statistik.lmu.de/~fkreuter/imputation_sose2011/downloads/…。私が正しく理解していれば、制約問題の潜在的な解決策について説明しています(スライド番号50ではなく、PDFの50ページを参照してください!)。お役に立てれば。
アレクサンドルブレフ14年

1
@ t0x1n:実際には、ソリューションはページ50と51に記述されている
アレクサンドルBlekh

0

私があなたの質問を正しく理解していれば、不足している変数がいくつかの制約を受けなければならない値をすでに知っているように思えます。私はSPSSにあまり精通していませんが、RIではそれを行う関数を書くことができると思います(私が言うべき経験によってはそれほど難しくないはずです)。私はそのような制約で動作するパッケージを知りません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.