拓端tecdat|R语言代写有RStan的多维验证性因子分析(CFA)

   2023-02-09 学习力0
核心提示:如果您已经熟悉RStan,那么您需要组合的基本概念是具有相关随机斜率和异方差误差的标准多级模型。我将R代码嵌入到演示中。所需的包是lavaan,lme4和RStan。我喜欢将大多数统计方法理解为回归模型。这样,很容易理解大量技术背后的主张。这是一种适用于多级,S

如果您已经熟悉RStan,那么您需要组合的基本概念是具有相关随机斜率和异方差误差的标准多级模型。

我将R代码嵌入到演示中。所需的包是lavaanlme4RStan

我喜欢将大多数统计方法理解为回归模型。这样,很容易理解大量技术背后的主张。这是一种适用于多级,SEM和IRT模型的方法。在这里,我将重点关注验证性因子分析(CFA),因此我将首先从一个易于适用于任何多级回归软件的模型开发CFA:

 

 

 
dat <- HolzingerSwineford1939
 dat$ID <- 1:nrow(dat)

# Make data long
dat.l <- tidyr::gather(dat, item, score, x1:x9)
dat.l$item.no <- as.integer(gsub("x", "", dat.l$item))

library(lme4)

lmer(score ~ 0 + factor(item.no) + (1 | ID), dat.l, REML = FALSE)

# Random effects:
# Groups   Name        Std.Dev.
# ID       (Intercept) 0.5758  
# Residual             0.9694  
# Number of obs: 2709, groups:  ID, 301

上面适用于ML而不是REML的模型与一维CFA相同,其中我们将所有项目加载限制为相同的值并且项目错误是相同的值。随机截距标准差,αα,是因子载荷为所有项目和σ 2σ2是所有项目的项目错误差异。为了得到我们称之为λ的标准化载荷λ, 使用:

λ = α √ α 2 + σ 2= 0.5758 √ 0.5758 2 + 0.9694 2= 0.5107λ=αα2+σ2=0.57580.57582+0.96942=0.5107

下面的熔岩模型应该证实这是真的。请注意,在lavaan语法中,因子被标准化为使用的方差为1 std.lv = TRUE。来自lme4的项目假人(未示出)也是CFA项目拦截。

parameterEstimates(sem(
  "F1 =~ a * x1 + a * x2 + a * x3 + a * x4 + a * x5 + a * x6 + a * x7 + a * x8 + a * x9\n
   x5 ~~ f * x5\nx6 ~~ f * x6\nx7 ~~ f * x7\nx8 ~~ f * x8\nx9 ~~ f * x9",
  dat, std.lv = TRUE
), standardized = TRUE)[c(1:2, 10:11), c(1:5, 12)]

#    lhs op rhs label   est std.all
# 1   F1 =~  x1     a 0.576   0.511
# 2   F1 =~  x2     a 0.576   0.511
# 10  x1 ~~  x1     f 0.940   0.739
# 11  x2 ~~  x2     f 0.940   0.739

标准化的加载具有类似的公式的(剩余)组内相关系数(ICC),该α 2 α 2 + σ 2α2α2+σ2。因此,我们有λ = √ 我Ç Çλ=一世CC。这与将标准化负载作为相关系数和ICC作为R 2的思考一致[R2。

现在,熟悉CFA的每个人都知道我们几乎从不约束所有项目加载和项目错误具有相同的价值 。但我们会尽可能长时间地保持CFA的回归。让我们扩展模型以包括多个因素。为了包括多个因子,我们以长格式创建一个指标列,用于唯一标识项目所属的因子。而不是使用单个随机截距,我们使用因子假人作为随机斜率而没有随机截距。 

# Assign item to factors
dat.l$Fs <- ((dat.l$item.no - 1) %/% 3) + 1

lmer(score ~ 0 + factor(item) + (0 + factor(Fs) | ID), dat.l, REML = FALSE)

# Random effects:
#  Groups   Name        Std.Dev. Corr     
#  ID       factor(Fs)1 0.7465            
#           factor(Fs)2 0.9630   0.41     
#           factor(Fs)3 0.6729   0.38 0.30
#  Residual             0.7909            

相应的lavaan模型是:

parameterEstimates(sem(
  "F1 =~ a * x1 + a * x2 + a * x3\nF2 =~ b * x4 + b * x5 + b * x6\nF3 =~ c * x7 + c * x8 + c * x9\n
  x1 ~~ f * x1\nx2 ~~ f * x2\nx3 ~~ f * x3\nx4 ~~ f * x4\nx5 ~~ f * x5\n
   dat, std.lv = TRUE
), standardized = TRUE)[c(1:10, 22:24), c(1:5, 12)]

#    lhs op rhs label   est std.all
# 1   F1 =~  x1     a 0.746   0.686
# 2   F1 =~  x2     a 0.746   0.686
# 3   F1 =~  x3     a 0.746   0.686
# 4   F2 =~  x4     b 0.963   0.773
# 5   F2 =~  x5     b 0.963   0.773
# 6   F2 =~  x6     b 0.963   0.773
# 7   F3 =~  x7     c 0.673   0.648
# 8   F3 =~  x8     c 0.673   0.648
# 9   F3 =~  x9     c 0.673   0.648
# 10  x1 ~~  x1     f 0.626   0.529
# 22  F1 ~~  F2       0.407   0.407
# 23  F1 ~~  F3       0.385   0.385
# 24  F2 ~~  F3       0.301   0.301

我们看到CFA中的因子载荷是多级的随机斜率标准偏差。并且,因子间相关矩阵匹配来自多级的随机斜率相关。

 在lavaan,模型语法将是:

# Drop the error variance constraints
"F1 =~ a * X1 + a * X2 + a * X3\nF2 =~ b * X4 + b * X5 + b * X6\nF3 =~c * X7 + c * X8 + c * X9"

最新型号非常接近标准CFA型号。最后的变化是我们需要允许项目加载量按项目而不是因子来变化。一旦我们这样做,我们就不能再使用多级回归软件来适应模型。 

贝叶斯软件可以适合这样的复杂模型。我们必须为这个等式的不同组成部分指定先验。 

 

在Stan语法中,所需的数据是:

data {
  real g_alpha; // for inverse gamma
  real g_beta; // for inverse gamma
    int<lower = 0> Nf; // scalar, number of factors
  vector[N] response; // vector, long form of item responses
  // all remaining entries are data in long form
  // with consecutive integers beginning at 1 acting as unique identifiers
  int<lower = 1, upper = Ni> items[N];
   int<lower = 1, upper = Nf> factors[N];
}

估计的参数是:

parameters {
  vector<lower = 0>[Ni] item_vars; // item vars heteroskedastic
   vector<lower = 0>[Ni] alphas; // loadings
  vector[Ni] betas; // item intercepts, default uniform prior
 }

我们需要一些转换参数来捕获项目响应的均值和方差。这是我们逐字提供回归方程的地方:

transformed parameters {
  vector[N] yhat;
  vector[N] item_sds_i;

  for (i in 1:N) {
    yhat[i] = alphas[items[i]] * thetas[persons[i], factors[i]] + betas[items[i]];
    item_sds_i[i] = sqrt(item_vars[items[i]]);
  }
}

对于先辈们:

model {
   matrix[Nf, Nf] A0;

  L ~ lkj_corr_cholesky(Nf);
  A0 = diag_pre_multiply(A, L);
  thetas ~ multi_normal_cholesky(rep_vector(0, Nf), A0);
 

  response ~ normal(yhat, item_sds_i);
}

最后,我们可以计算标准化载荷和因子间相关矩阵R:

generated quantities {
  vector<lower = 0>[Ni] loadings_std; // obtain loadings_std
  matrix[Nf, Nf] R;
 
  }
}

我们可以做一些修改:

  • 我们可以在建模之前标准化项目响应,以提高计算稳定性
  • 然后在项目截取之前应用法线

然后运行模型的语法是:

# First, let's fit the model in lavaan:
 
 
cfa.mm <- stan_model(stanc_ret = stanc(file = "bayes_script/cfa.stan")) # Compile Stan code
 

什么是负荷?

 

#                  mean se_mean    sd  2.5%   50% 97.5% n_eff  Rhat
# alphas[1]       0.889   0.003 0.078 0.733 0.890 1.041   790 1.002
# alphas[4]       0.991   0.002 0.056 0.885 0.988 1.101  1263 1.002
# alphas[5]       1.102   0.002 0.062 0.980 1.102 1.224  1056 1.001
# alphas[9]       0.692   0.003 0.075 0.548 0.692 0.846   799 1.005
# loadings_std[1] 0.751   0.002 0.052 0.643 0.752 0.848   601 1.003
# loadings_std[4] 0.848   0.001 0.023 0.801 0.849 0.890  1275 1.003
# loadings_std[5] 0.851   0.001 0.023 0.803 0.852 0.891  1176 1.001
# loadings_std[9] 0.672   0.003 0.059 0.552 0.673 0.786   556 1.007

# For comparison, the lavaan loadings are:
parameterEstimates(cfa.lav.fit, standardized = TRUE)[1:9, c(1:5, 11)]

#   lhs op rhs   est    se std.all
# 1  F1 =~  x1 0.900 0.081   0.772
# 4  F2 =~  x4 0.990 0.057   0.852
# 5  F2 =~  x5 1.102 0.063   0.855
# 9  F3 =~  x9 0.670 0.065   0.665

对于因子间相关性:

       probs = c(.025, .5, .975), digits_summary = 3)

#       mean se_mean    sd  2.5%   50% 97.5% n_eff  Rhat
# R[1,2] 0.435   0.001 0.065 0.303 0.437 0.557  2019 0.999
# R[1,3] 0.451   0.003 0.081 0.289 0.450 0.607   733 1.005
# R[2,3] 0.271   0.001 0.071 0.130 0.272 0.406  2599 1.000

# From lavaan:
 
#    lhs op rhs   est    se std.all
# 22  F1 ~~  F2 0.459 0.064   0.459
# 23  F1 ~~  F3 0.471 0.073   0.471
# 24  F2 ~~  F3 0.283 0.069   0.283

对于错误差异:

 
#               mean se_mean    sd  2.5%   50% 97.5% n_eff  Rhat
# item_vars[3] 0.829   0.003 0.095 0.652 0.828 1.026  1292 1.000
# item_vars[4] 0.383   0.001 0.049 0.292 0.381 0.481  1552 1.002
# item_vars[5] 0.459   0.001 0.059 0.351 0.456 0.581  1577 1.001
# item_vars[9] 0.575   0.004 0.085 0.410 0.575 0.739   532 1.008

# From lavaan:
parameterEstimates(cfa.lav.fit, standardized = TRUE)[10:18, 1:5]

#    lhs op rhs   est    se
# 12  x3 ~~  x3 0.844 0.091
# 13  x4 ~~  x4 0.371 0.048
# 14  x5 ~~  x5 0.446 0.058
# 18  x9 ~~  x9 0.566 0.071

对于项目 :

 

#         mean se_mean    sd  2.5%   50% 97.5% n_eff  Rhat
# betas[2] 6.087   0.001 0.068 5.954 6.089 6.219  2540 1.001
# betas[3] 2.248   0.001 0.066 2.122 2.248 2.381  1980 1.002
# betas[6] 2.182   0.003 0.063 2.058 2.182 2.302   625 1.008
# betas[7] 4.185   0.002 0.066 4.054 4.186 4.315  1791 1.001

# From lavaan:
parameterEstimates(cfa.lav.fit, standardized = TRUE)[25:33, 1:5]
#    lhs op rhs   est    se
# 26  x2 ~1     6.088 0.068
# 27  x3 ~1     2.250 0.065
# 30  x6 ~1     2.186 0.063
# 31  x7 ~1     4.186 0.063

所以我们能够复制lavaan的结果。从这里,您可以以有趣的方式扩展模型以获得其他结果。


例如,如果要对因子进行回归,可以使用相关矩阵的后验和solve()函数来得出回归中因子的系数。在这里,我在因子2和3上回归因子1:

R <- extract(cfa.stan.fit, c("R[1, 2]", "R[1, 3]", "R[2, 3]"))
R <- cbind(R$`R[1,2]`, R$`R[1,3]`, R$`R[2,3]`)
coefs <- matrix(NA, nrow(R), ncol(R) - 1)
for (i in 1:nrow(R)) {
  m <- matrix(c(1, R[i, 3], R[i, 3], 1), 2, 2)
  coefs[i, ] <- solve(m, R[i, 1:2])
}; rm(i, m)
t(apply(coefs, 2, function (x) {
  c(estimate = mean(x), sd = sd(x), quantile(x, c(.025, .25, .5, .75, .975)))
}))
#       estimate         sd      2.5%       25%       50%       75%     97.5%
# [1,] 0.3362981 0.07248634 0.1918812 0.2877936 0.3387682 0.3875141 0.4725508
# [2,] 0.3605951 0.08466494 0.1996710 0.3027047 0.3594806 0.4164141 0.5308578

 

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • 拓端tecdat|R语言VAR模型的不同类型的脉冲响应
    原文链接:http://tecdat.cn/?p=9384目录模型与数据估算值预测误差脉冲响应识别问题正交脉冲响应结构脉冲反应广义脉冲响应参考文献脉冲响应分析是采用向量自回归模型的计量经济学分析中的重要一步。它们的主要目的是描述模型变量对一个或多个变量的冲击的演化
    03-16
  • Visual Studio 编辑R语言环境搭建
    Visual Studio 编辑R语言环境搭建关于Visual Studio 编辑R语言环境搭建具体的可以看下面三个网址里的内容,我这里就讲两个问题,关于r包管理和换本地的r的服务。1.r包管理:Ctrl+72.R本地服务管理:Ctrl+9Visual Studio R官方帮助文档(中文): https://docs
    03-16
  • 拓端tecdat|R语言代写实现向量自回归VAR模型
    原文链接:http://tecdat.cn/?p=8478 澳大利亚在2008 - 2009年全球金融危机期间发生了这种情况。澳大利亚政府发布了一揽子刺激计划,其中包括2008年12月的现金支付,恰逢圣诞节支出。因此,零售商报告销售强劲,经济受到刺激。因此,收入增加了。VAR面临的批
    03-16
  • [译]用R语言做挖掘数据《五》 r语言数据挖掘简
    一、实验说明1. 环境登录无需密码自动登录,系统用户名shiyanlou,密码shiyanlou2. 环境介绍本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到程序:1. LX终端(LXTerminal): Linux命令行终端,打开后会进入Bash环境,可以使用Linux命令2. GVim:非常好
    03-08
  • 拓端tecdat|Mac系统R语言升级后无法加载包报错 package or namespace load failed in dyn.load(file, DLLpath = DLLpath, ..
    拓端tecdat|Mac系统R语言升级后无法加载包报错
    问题重现:我需要安装R软件包stochvol,该软件包 仅适用于3.6.0版的R。因此,我安装了R(3.6.0 版本),并使用打开它 RStudio。但是现在  ,即使我成功 使用来 安装软件包,也无法加载任何库 。具体来说,我需要加载的库是stochvol  ,Rcpp和 caret
    03-08
  • 拓端数据tecdat|R语言k-means聚类、层次聚类、主成分(PCA)降维及可视化分析鸢尾花iris数据集
    拓端数据tecdat|R语言k-means聚类、层次聚类、
    原文链接:http://tecdat.cn/?p=22838 原文出处:拓端数据部落公众号问题:使用R中的鸢尾花数据集(a)部分:k-means聚类使用k-means聚类法将数据集聚成2组。 画一个图来显示聚类的情况使用k-means聚类法将数据集聚成3组。画一个图来显示聚类的情况(b)部分:
    03-08
  • 《R语言数据挖掘》读书笔记:七、离群点(异常值)检测
    《R语言数据挖掘》读书笔记:七、离群点(异常值
    第七章、异常值检测(离群点挖掘)概述:        一般来说,异常值出现有各种原因,比如数据集因为数据来自不同的类、数据测量系统误差而收到损害。根据异常值的检测,异常值与原始数据集中的常规数据显著不同。开发了多种解决方案来检测他们,其中包括
    03-08
  • 拓端数据tecdat|R语言中实现广义相加模型GAM和普通最小二乘(OLS)回归
    拓端数据tecdat|R语言中实现广义相加模型GAM和
    原文链接:http://tecdat.cn/?p=20882  1导言这篇文章探讨了为什么使用广义相加模型 是一个不错的选择。为此,我们首先需要看一下线性回归,看看为什么在某些情况下它可能不是最佳选择。 2回归模型假设我们有一些带有两个属性Y和X的数据。如果它们是线性
    03-08
  • 拓端数据tecdat|R语言时间序列平稳性几种单位根检验(ADF,KPSS,PP)及比较分析
    拓端数据tecdat|R语言时间序列平稳性几种单位根
    原文链接:http://tecdat.cn/?p=21757 时间序列模型根据研究对象是否随机分为确定性模型和随机性模型两大类。随机时间序列模型即是指仅用它的过去值及随机扰动项所建立起来的模型,建立具体的模型,需解决如下三个问题模型的具体形式、时序变量的滞后期以及随
    03-08
  • 拓端tecdat|R语言风险价值VaR(Value at Risk)和损失期望值ES(Expected shortfall)的估计
    拓端tecdat|R语言风险价值VaR(Value at Risk)
    原文链接: http://tecdat.cn/?p=15929 风险价值VaR和损失期望值ES是常见的风险度量。首先明确:时间范围-我们展望多少天?概率水平-我们怎么看尾部分布?在给定时间范围内的盈亏预测分布,示例如图1所示。  图1:预测的损益分布 给定概率水平的预测的分
    03-08
点击排行