如何将置信区间添加到 MARSS 包 DFA 因子加载

How to add confidence intervals to MARSS package DFA factor loadings

我正在尝试为 MARSS DFA 分析添加 95% 的置信区间。我的代码

library(MARSS) ## version 3.10.12
library(dplyr)
library(tidyr)
library(ggplot2)

data(lakeWAplankton, package = "MARSS")

all_dat <- lakeWAplanktonTrans
yr_frst <- 1980
yr_last <- 1989
plank_dat <- all_dat[all_dat[, "Year"] >= yr_frst & all_dat[, "Year"] <= yr_last, ]

phytoplankton <- c("Cryptomonas", "Diatoms", "Greens", "Unicells", 
                   "Other.algae")
## get only the phytoplankton
dat_1980 <- plank_dat[, phytoplankton]

## transpose data so time goes across columns
dat <- t(dat_1980)

mod_list = list(m = 3, R = "diagonal and unequal")
con_list <- list(maxit = 3000, allow.degen = TRUE)
dfa_temp <- MARSS(dat, model = mod_list, form = "dfa", z.score = FALSE, 
                  control = con_list)

dfa_temp <- MARSSparamCIs(dfa_temp)


up = coef(dfa_temp, what = "par.upCI")$Z
lo = coef(dfa_temp, what = "par.lowCI")$Z
raw = coef(dfa_temp, what = "par")$Z
ci_list <- list(up = up, lo = lo, raw = raw)

f = dfa_temp$marss$fixed$Z
d = dfa_temp$marss$free$Z

dims = attr(dfa_temp$marss, "model.dims")$Z
par_names <- rownames(dfa_temp$call$data)

delem = d
attr(delem, "dim") = attr(delem, "dim")[1:2]

felem = f
attr(felem, "dim") = attr(felem, "dim")[1:2]

par_mat <- lapply(1:3, function(x) matrix(felem + delem %*% ci_list[[x]],
                                          dims[1], dims[2]))
names(par_mat) <- names(ci_list)

h_inv = varimax(par_mat$raw)$rotmat
h_inv_lo = varimax(par_mat$lo)$rotmat
h_inv_up = varimax(par_mat$up)$rotmat
z_rot = data.frame(var = "raw", par_mat$raw %*% h_inv)
z_rot_lo = data.frame(var = "lo", par_mat$lo %*% h_inv_lo)
z_rot_up = data.frame(var = "up", par_mat$up %*% h_inv_up)

loads <- rbind(z_rot, z_rot_lo, z_rot_up)
colnames(loads)[2:4] <- c("trend_1", "trend_2", "trend_3")
loads$plank <- rep(row.names(dat), 3)

loads_long <- pivot_longer(loads, cols = c("trend_1", "trend_2", "trend_3"),
                                  names_to = "trend", values_to = "val")

loads_dat <- pivot_wider(loads_long, names_from = var, values_from = val)

ggplot(data = loads_dat, 
       aes(x = plank, 
           ymin = lo,
           ymax = up,
           y = raw)) +
  geom_hline(yintercept = 0, color = "black") +
  geom_pointrange() +
  facet_wrap(~trend) +
  coord_flip() +
  theme_bw()

我预计原始因子加载值相对接近 95% 的中间值 CI,但生成的误差条与点不一致。

问题 1:方差最大旋转和矩阵数学是否正确以得出 MARSS DFA 因子载荷?
问题 2:是否有更简单(且正确!!)的方法来将置信区间添加到因子载荷?

您想旋转上下Z矩阵。不幸的是,您的问题导致在 coef() 函数中发现了一个错误,这使得很难获得这些错误。但是这段代码是解决这个问题的一种方法。它使用 coef() 用来获取参数矩阵的内部函数。

# add the par.lowCI and par.upCI to the fit
dfa_temp <- MARSSparamCIs(dfa_temp)

# get the rotation matrix for the Z
Z <- coef(dfa_temp, type = "matrix")$Z
H.inv <- varimax(Z)$rotmat

# Get the upZ, lowZ
# normally this would work coef(dfa_temp, type="matrix", what="par.lowCI")
# but there is a bug and it is not respecting type="matrix"
# I use the internal function parmat() which is using the $par element
#  just need to replace $par with the upper and lower pars
tmp <- dfa_temp; tmp$par <- tmp$par.upCI
Z.up <- MARSS:::parmat(tmp)$Z
tmp <- dfa_temp; tmp$par <- tmp$par.lowCI
Z.low <- MARSS:::parmat(tmp)$Z

Z.rot <- Z %*% H.inv
Z.rot.up <- Z.up %*% H.inv
Z.rot.low <- Z.low %*% H.inv

df <- data.frame(Z=as.vector(Z.rot), Zup=as.vector(Z.rot.up), Zlow=as.vector(Z.rot.low))