階層/マルチレベルデータのブートストラップ(クラスターのリサンプリング)


9

cats-MASS-パッケージから)データセットからブートストラップサンプルを作成するためのスクリプトを作成しています。

DavidsonとHinkleyの教科書[1]に従い、私は単純な線形回帰を実行し、iidの観測、つまりペアのリサンプリングからブートストラップするための基本的なノンパラメトリック手順を採用しました。

元のサンプルは次の形式です。

Bwt   Hwt

2.0   7.0
2.1   7.2

...

1.9    6.8

単変量線形モデルを通じて、猫の囲いの重量を脳の重量で説明したいと思います。

コードは次のとおりです。

library(MASS)
library(boot)


##################
#   CATS MODEL   #
##################

cats.lm <- glm(Hwt ~ Bwt, data=cats)
cats.diag <- glm.diag.plots(cats.lm, ret=T)


#######################
#   CASE resampling   #
#######################

cats.fit <- function(data) coef(glm(data$Hwt ~ data$Bwt)) 
statistic.coef <- function(data, i) cats.fit(data[i,]) 

bootl <- boot(data=cats, statistic=statistic.coef, R=999)

ここで、クラスタリング変数が存在するとしますcluster = 1, 2,..., 24(たとえば、各猫は特定のごみに属しています)。簡単にするために、データのバランスが取れていると仮定します。各クラスターに6つの観測があります。したがって、24匹の同腹児はそれぞれ6匹の猫(つまりn_cluster = 6n = 144)で構成されています。

偽のcluster変数を作成することは可能です:

q <- rep(1:24, times=6)
cluster <- sample(q)
c.data <- cbind(cats, cluster)

関連する質問が2つあります。

(クラスター化された)データセット構造に従ってサンプルをシミュレートする方法は?つまり、クラスターレベルでリサンプリングする方法クラスターを置換してサンプリングし、選択した各クラスター内の観測を元のデータセットのように設定します(つまり、クラスターを置換してサンプリングし、各クラスター内の観測を置換せずにサンプリングします)。

これは、Davidson(p。100)によって提案された戦略です。B = 100サンプルを描画するとします。それらのそれぞれは、24の再発する可能性のあるクラスター(例:)で構成される必要がcluster = 3, 3, 1, 4, 12, 11, 12, 5, 6, 8, 17, 19, 10, 9, 7, 7, 16, 18, 24, 23, 11, 15, 20, 1あり、各クラスターには元のデータセットの同じ6つの観測が含まれている必要があります。それをどのように行うのRですか?(-boot-パッケージの有無にかかわらず)続行するための代替提案はありますか?

2番目の質問は、初期回帰モデルに関するものです。クラスターレベルの切片を使用して、固定効果モデルを採用するとします。採用されたリサンプリング手順は変わりますか?

[1]デビッドソン、AC、ヒンクリー、DV(1997)。ブートストラップメソッドとそのアプリケーション。ケンブリッジ大学出版局。

回答:


9

クラスタ全体のリサンプリングは、そこで再サンプリング手法が使用されている限り(つまり、1960年代中頃以降)、調査統計で知られているため、十分に確立された方法です。http://www.citeulike.org/user/ctacmo/tag/survey_resamplingで私のリンク集をご覧くださいbootこれができるかどうかはわかりません。survey調査ブートストラップを使用する必要がある場合は、パッケージを使用しますが、前回確認したときは、必要な機能がすべてありませんでした(思い出せる限り、いくつかの小さなサンプルの修正など)。

固定効果などの特定のモデルを適用すると状況が大きく変わるとは思いませんが、IMO、残差ブートストラップは多くの強力な仮定を行います(残差はiid、モデルは正しく指定されています)。それらのすべてが簡単に壊れ、クラスター構造は確かにiidの仮定を破ります。

ワイルドクラスターブートストラップに関する計量経済学の文献がいくつかあります。彼らは、このトピックに関する50年間の調査統計調査を行わずに、彼らが真空で働いていると偽ったので、それをどうするべきか私にはわかりません。


クラスターレベルで固定効果を作成することについての私の主な疑問は、一部のシミュレートされたサンプルでは、​​一部の初期クラスターを選択していないことがあり、関連するクラスター固有の切片を識別できない場合があることです。私が投稿したコードを見れば、「機械的」な観点からは問題になりません(各反復で、サンプリングされたクラスターの切片のみを使用して異なるFEモデルに適合させることができます)。このすべてに「統計的」な問題があるかどうか疑問に思いました
Stefano Lombardi

3

私は自分で問題を解決しようとし、次のコードを生成しました。

動作しますが、速度の点で改善される可能性があります。また、可能であれば、-boot-パッケージを使用する方法を見つけることをお勧めします。これにより、ブートストラップされた信頼区間の数を自動的に計算できますboot.ci...

簡単にするために、開始時のデータセットは、6つの実験室(クラスタリング変数)にネストされた18匹の猫(「下位レベル」の観測)で構成されています。データセットは(n_cluster = 3各クラスターについて)バランスが取れています。x説明するために、1つのリグレッサがありyます。

偽のデータセットと結果を格納するマトリックスは次のとおりです。

  # fake sample 
  dat <- expand.grid(cat=factor(1:3), lab=factor(1:6))
  dat <- cbind(dat, x=runif(18), y=runif(18, 2, 5))

  # empty matrix for storing coefficients estimates and standard errors of x
  B <- 50 # number of bootstrap samples
  b.sample <- matrix(nrow=B, ncol=3, dimnames=list(c(), c("sim", "b_x", "se_x")))
  b.sample[,1] <- rep(1:B)

B次のループは、各反復で、置換された6つのクラスターをサンプリングします。各クラスターは、置換なしでサンプリングされた3つの猫で構成されます(つまり、クラスターの内部構成は変更されずに維持されます)。リグレッサ係数とその標準誤差の推定値は、以前に作成された行列に格納されます。

  ####################################
  #   loop through "b.sample" rows   #
  ####################################

  for (i in seq(1:B)) {

  ###   sampling with replacement from the clustering variable   

    # sampling with replacement from "cluster" 
    cls <- sample(unique(dat$lab), replace=TRUE)
    cls.col <- data.frame(lab=cls)

    # reconstructing the overall simulated sample
    cls.resample <- merge(cls.col, dat, by="lab")


  ###   fitting linear model to simulated data    

    # model fit
    mod.fit <- function(data) glm(data$y ~ data$x)

    # estimated coefficients and standard errors
    b_x <- summary(mod.fit(data=cls.resample))$coefficients[2,1]
    	se_x <- summary(mod.fit(data=cls.resample))$coefficients[2,2]

    b.sample[i,2] <- b_x
    b.sample[i,3] <- se_x

  }

Landoがお役に立てば幸いです


forループを使用する必要があります使用することによって支配されますreplicate。おまけとして、自動的にb.sample配列を返します。また、ここでのすべてのマージにより、を使用data.tableしてリサンプリングする方が確実に良いでしょうkey。コンピュータにアクセスしたときに答えを出すことがあります...質問:なぜ係数の標準誤差を追跡しているのですか?
MichaelChirico

@MichaelChiricoに感謝します、同意します。私がよく覚えている場合、後で信頼区間をプロットするために標準エラーを保存していました。
Stefano Lombardi

信頼区間は、ブートストラップ係数の分布の分位点であってはなりませんか?つまり、95%信頼区間の場合quantile(b.sample[,2], c(.025, .975))
MichaelChirico

3

これは、data.table(@ lando.carlissianのデータに対して)を使用してブートストラップを実行する、はるかに単純な(そしてほぼ間違いなく高速な)方法です。

library(data.table)
setDT(dat, key = "lab")
b.sample <- 
  replicate(B, dat[.(sample(unique(lab), replace = T)),
                   glm(y ~ x)$coefficients])

2

私は最近これをしなければならず、使用しましたdplyr。ソリューションはほどエレガントではありませんdata.tableが、次のようになります。

library(dplyr)
replicate(B, {
  cluster_sample <- data.frame(cluster = sample(dat$cluster, replace = TRUE))
  dat_sample <- dat %>% inner_join(cluster_sample, by = 'cluster')
  coef(lm(y ~ x, data = dat_sample))
})

inner_join与えられた値を有するすべての行繰り返しxcluster回数によってxに表示をcluster_sample


0

こんにちは、splitとlapplyに基づく非常にシンプルなソリューションです。「boot」以外の特定のパッケージは不要です。たとえば、nagakawaの手順に基づくICCの推定を使用します。

# FIRST FUNCTION : "parameter assesment"
nagakawa <- function(dataICC){
    #dataICC <- dbICC
    modele <- lmer(indicateur.L ~ 1 + (1|sujet.L) + (1|injection.L) + experience.L, data = dataICC)
    variance <- get_variance(modele)
    var.fixed <- variance$var.fixed
var.random <- variance$var.random
    var.sujet <- variance$var.intercept[1]
var.resid <- variance$var.residual
    icc.juge1 <- var.random / (var.random + var.fixed + var.resid)

    modele <- lmer(indicateur.L ~ 1 + (1 + injection.L|sujet.L) + experience.L, data = dataICC)
    variance <- VarCorr(modele)
    var.fixed <- get_variance_fixed(modele)
    var.random <- (attributes(variance$sujet.L)$stddev[1])^2 + (attributes(variance$sujet.L)$stddev[2])^2
    var.sujet <- (attributes(variance$sujet.L)$stddev[1])^2
    var.resid <- (attributes(variance)$sc)^2
icc.juge2 <- var.random / (var.random + var.fixed + var.resid)
return(c(as.numeric(icc.juge1),as.numeric(icc.juge2)))
  }
```
#SECOND FONCTION : bootstrap function, split on the hirarchical level as you want
```
  nagakawa.boot <- function(data,x){
list.ICC <- split(x = data, f = paste(data$juge.L,data$injection.L,sep = "_"))
    list.BOOT <- lapply(X = list.ICC, FUN = function(y){
      y[x,]
    })
    db.BOOT <- do.call(what = "rbind", args = list.BOOT)
    nagakawa(dataICC = db.BOOT)
  }

THIRD:ブートストラップ実行

ICC.BOOT <- boot(data = dbICC, statistic = nagakawa.boot, R = 1000)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.