缺少数据的 Cronbach Alpha

机器算法验证 r 缺失数据 可靠性 cronbachs-alpha
2022-04-06 13:44:17

R中,有几个包可以计算 Cronbach 的 alpha。如果数据不包含缺失值,我访问的所有包都会收敛到相同的值。对于缺少数据,按列表删除是一种可能的方法(SPSS 或包MBESSpsybtw 中的唯一选项)。但是,按列表删除可能会导致删除大量数据,因此在某些情况下(假设数据是 MCAR),成对删除之类的东西可能看起来更有吸引力。
其中一些包具有类似的选项na.rm = T,但结果不同,并且数据集包含的缺失越多,它们的差异越大。其原因是方差-协方差矩阵的计算。例如,该封装采用了强大的ScoefficientalphaS矩阵自然会导致不同的结果。但是,其他包使用成对 矩阵,结果仍然不同。 让我们举一个具体的例子。alpha 的公式是 )项目数,第个项目和总分的方差对于分母的总方差,包使用类似的东西,而包使用类似的东西这两个估计值对于完整数据是相同的,但对于缺失数据是不同的。(包裹S

α=pp1(1i=1pσyi2σx2)
piσyi2σx2ltmvar(rowSums(dat, na.rm = T))psychsum(cov(dat, use = "pairwise"))epicalc似乎使用了第三种计算方差的方法,但我还没有掌握他们的代码。)的不同计算的原因是什么,我什么时候应该使用哪一个?σx2

> require("MASS", "psych", "ltm")
> n <- 200
> it <- 10
> V <- matrix(.4, ncol = it, nrow = it)
> diag(V) <- 1
> dat <- mvrnorm(n, rep(0, it), V)   # complete data
> m1 <- matrix(rbinom(n * it, 1, .1), nrow = n, ncol = it)   # 10% missings
> dat[m1 == 1] <- NA   # missing data
> alpha(as.data.frame(dat), na.rm = T)$total[[1]]   # psych package  
[1] 0.8595489
> cronbach.alpha(dat, na.rm = T)$alpha   # ltm package
[1] 0.8105867
1个回答

如果数据是 MCAR,则希望找到 alpha 的无偏估计。这可以通过多重插补或列表删除来完成。但是,后者可能会导致严重的数据丢失。第三种方式类似于成对删除,它通过包中的na.rm选项alpha()ltm包中cronbach.alpha()的选项来实现psych

至少恕我直言,以前对缺失数据的非标准化 alpha 的估计有偏差的(见下文)。这是由于通过 计算总方差\如果数据以 0 为中心,则正值和负值在 的计算中相互抵消由于缺少数据,这会导致偏向0,因此会低估(以及 alpha)。相反,如果数据大部分是正数(或负数),那么这次缺失将导致偏向零,从而导致高估(以及 alpha)。σx2var(rowSums(dat, na.rm = TRUE))rowSumsrowSumsσx2rowSumsσx2

require("MASS"); require("ltm"); require("psych")
n <- 10000
it <- 20
V <- matrix(.4, ncol = it, nrow = it)
diag(V) <- 1
dat <- mvrnorm(n, rep(0, it), V)  # mean of 0!!!
p <- c(0, .1, .2, .3)
names(p) <- paste("% miss=", p, sep="")
cols <- c("alpha.ltm", "var.tot.ltm", "alpha.psych", "var.tot.psych")
names(cols) <- cols
res <- matrix(nrow = length(p), ncol = length(cols), dimnames = list(names(p), names(cols)))
for(i in 1:length(p)){
  m1 <- matrix(rbinom(n * it, 1, p[i]), nrow = n, ncol = it)
  dat1 <- dat
  dat1[m1 == 1] <- NA
  res[i, 1] <- cronbach.alpha(dat1, standardized = FALSE, na.rm = TRUE)$alpha
      res[i, 2] <- var(rowSums(dat1, na.rm = TRUE))
      res[i, 3] <- alpha(as.data.frame(dat1), na.rm = TRUE)$total[[1]]
  res[i, 4] <- sum(cov(dat1, use = "pairwise"))
}
round(res, 2)
##            alpha.ltm var.tot.ltm alpha.psych var.tot.psych
## % miss=0        0.93      168.35        0.93        168.35
## % miss=0.1      0.90      138.21        0.93        168.32
## % miss=0.2      0.86      110.34        0.93        167.88
## % miss=0.3      0.81       86.26        0.93        167.41
dat <- mvrnorm(n, rep(10, it), V)  # this time, mean of 10!!!
for(i in 1:length(p)){
  m1 <- matrix(rbinom(n * it, 1, p[i]), nrow = n, ncol = it)
  dat1 <- dat
  dat1[m1 == 1] <- NA
  res[i, 1] <- cronbach.alpha(dat1, standardized = FALSE, na.rm = TRUE)$alpha
      res[i, 2] <- var(rowSums(dat1, na.rm = TRUE))
      res[i, 3] <- alpha(as.data.frame(dat1), na.rm = TRUE)$total[[1]]
  res[i, 4] <- sum(cov(dat1, use = "pairwise"))
}
round(res, 2)
##            alpha.ltm var.tot.ltm alpha.psych var.tot.psych
## % miss=0        0.93      168.31        0.93        168.31
## % miss=0.1      0.99      316.27        0.93        168.60
## % miss=0.2      1.00      430.78        0.93        167.61
## % miss=0.3      1.01      511.30        0.93        167.43