Após a seleção dos modelos e o pré-processamento, a presente seção estima as duas especificações da AFC na subamostra de calibração. A estimação traduz as relações previstas nos modelos teóricos em parâmetros empíricos, sob as condições estabelecidas nas etapas anteriores: tratamento contínuo dos itens, estimador MLR, procedimento FIML e identificação pela fixação unitária da variância dos fatores (Jackson et al., 2009; Nye, 2022).
Os 1.243 participantes da amostra de análise foram divididos aleatoriamente em duas parcelas: 621 para calibração e 622 para validação. A partição foi estratificada pela presença de respostas ausentes nos 24 indicadores, distribuindo os 60 participantes com alguma omissão de forma equilibrada entre os dois grupos. A subamostra de calibração é empregada para estimar os modelos e examinar seus diagnósticos, ao passo que a subamostra de validação é reservada à confirmação empírica da reespecificação selecionada.
6.1 Fundamentação da estimação
Os itens foram tratados como variáveis contínuas, conforme a fundamentação desenvolvida na Seção 2.4. De acordo com Rhemtulla et al. (2012), o estimador MLR exibe desempenho adequado em configurações com cinco ou mais categorias ordinais, em especial quando os limiares de resposta distribuem-se de maneira aproximadamente simétrica. Robitzsch (2020) e Robitzsch (2022) demonstram que as formulações contínua e ordinal definem alvos paramétricos distintos. Com cinco categorias e uma estrutura fatorial previamente fundamentada, adota-se a formulação contínua como aproximação de mensuração no presente estudo.
O método MLR foi selecionado por combinar a ML com erros-padrão robustos e estatísticas de teste corrigidas por escala. Essa combinação ajusta-se com precisão às distribuições observadas no pré-processamento e atende às recomendações metodológicas para dados sob violação de normalidade multivariada (Brown, 2015; Kline, 2023; Rogers, 2024).
O volume residual de respostas ausentes foi tratado por meio do FIML. O procedimento aproveita toda a informação observada de cada respondente e preserva os 621 casos da subamostra de calibração. A opção segue as diretrizes da literatura para tratamento de dados omissos sob o método de ML e suas variantes robustas (Brown, 2023; Kline, 2023).
A escala dos fatores latentes foi definida fixando-se suas variâncias em 1. Essa estratégia de identificação permite estimar livremente todas as cargas fatoriais e assegura a mesma métrica nos dois modelos alternativos. Ambas as especificações foram estimadas sobre a mesma subamostra de calibração e sob condições analíticas idênticas. A comparação empírica concentra-se, assim, nas três relações cruzadas adicionais postuladas no modelo H1(Jackson et al., 2009; Nye, 2022).
NotaComo as amostras de calibração e validação foram obtidas
Finalidade
Dividir a base de dados em duas subamostras (calibração e validação), balanceando a presença de respostas incompletas em ambas. A subamostra de calibração viabiliza a estimação e os diagnósticos dos modelos; a de validação destina-se à confirmação da especificação selecionada.
Preparação
Utiliza-se Data/AnalysisData/whoqol_analysis.csv, gerado na etapa de pré-processamento (Seção 5), conforme a estrutura descrita na Seção 3. A partição abrange os 24 indicadores (Q3–Q26), antes de qualquer exclusão de itens.
Procedimento
O chunk abaixo lê a base, preserva os identificadores como texto e ordena os registros por ID. A variável missing_flag recebe 0 para quem respondeu aos 24 indicadores e 1 para quem apresenta omissões nesse conjunto. Esses dois estratos orientam o sorteio aleatório.
Em cada estrato, a semente fixa a partição de metade dos registros para a subamostra de calibração. Quando o estrato tem tamanho ímpar, o registro excedente é alocado na validação. O vetor sample_group identifica a subamostra: 0 para calibração e 1 para validação. Essa variável também pode identificar grupos em análises de invariança, distinguindo-se de missing_flag, restrita à estratificação de ausências.
O objeto cv_data conserva todos os participantes e as duas flags. A partição é salva em Data/AnalysisData/whoqol_cv.csv; nas execuções subsequentes, o bloco lê esse arquivo e verifica sua integridade com os dados de entrada. Assim, as seções posteriores recuperam exatamente a mesma partição, de forma reprodutível e independente da sessão.
Execução e resultado
Execute o bloco abaixo antes da Tabela 6.1. Ele mantém a base completa em cv_data e extrai calibration_data para a estimação dessa seção. A subamostra de validação permanece identificada por sample_group == 1 no arquivo gravado e será recuperada na etapa oportuna, preservando-se a integridade do banco original.
Código
# Read and order the complete analysis sample before splitting it.cv_data<-readr::read_csv2(here::here("Data", "AnalysisData", "whoqol_analysis.csv"), na =c("", "NA"), col_types =readr::cols(ID =readr::col_character()), show_col_types =FALSE)cv_data<-cv_data[order(cv_data$ID), ]# Identify incomplete responses using all 24 planned indicators.cv_data$missing_flag<-as.integer(rowSums(is.na(cv_data[paste0("Q", 3:26)]))>0L)stopifnot(!anyNA(cv_data$ID), !anyDuplicated(cv_data$ID))# Reuse the saved partition when its input data remain unchanged.cv_file<-here::here("Data", "AnalysisData", "whoqol_cv.csv")if(file.exists(cv_file)){saved_cv<-readr::read_csv2(cv_file, na =c("", "NA"), col_types =readr::cols( ID =readr::col_character(), missing_flag =readr::col_integer(), sample_group =readr::col_integer()), show_col_types =FALSE)stopifnot(identical(as.data.frame(saved_cv[names(cv_data)]), as.data.frame(cv_data)),all(saved_cv$sample_group%in%c(0, 1)))cv_data$sample_group<-as.integer(saved_cv$sample_group)}else{# Assign calibration (0) and validation (1) within each missingness stratum.set.seed(SEED)cv_data$sample_group<-1Lfor(stratumin0:1){stratum_rows<-which(cv_data$missing_flag==stratum)calibration_rows<-stratum_rows[sample.int(length(stratum_rows), size =floor(length(stratum_rows)/2))]cv_data$sample_group[calibration_rows]<-0L}# Preserve the original data and save the partition for later sections.dir.create(dirname(cv_file), recursive =TRUE, showWarnings =FALSE)readr::write_excel_csv2(cv_data, cv_file, na ="NA")}# Check stratum allocation and select the calibration sample.stopifnot(all(table(cv_data$missing_flag, cv_data$sample_group)[, "0"]==floor(table(cv_data$missing_flag)/2)))calibration_data<-cv_data[cv_data$sample_group==0L, ]
6.2 Parâmetros estimados
Antes da avaliação do ajuste, a Tabela 6.1 apresenta os parâmetros fatoriais estimados. Para cada relação entre fator e item, a tabela sintetiza a carga não padronizada, o erro-padrão robusto, a estatística \(z\) de teste e a carga padronizada, conforme recomendado por Jackson et al. (2009) e Nye (2022).
As cargas não padronizadas reportam a métrica original da escala. Por sua vez, as cargas padronizadas viabilizam a comparação direta da magnitude das relações em cada especificação, enquanto os erros-padrão asseguram inferência estatística corrigida para desvios de normalidade pelo método MLR.
A tabela consolida ambos os modelos, evidenciando as três relações adicionais de H1 ao lado das cargas primárias. A avaliação dessas cargas conjuga os parâmetros estimados aos índices de ajuste global e local examinados nas seções subsequentes.
Tabela 6.1: Parâmetros fatoriais estimados nos modelos H0 e H1.
Estimar os dois modelos na subamostra de calibração e consolidar as cargas fatoriais em tabela única, contendo estimativas não padronizadas, erros-padrão robustos, estatísticas \(z\) e cargas padronizadas.
Preparação
O procedimento utiliza as especificações analyzemodel e h1modelfree, definidas em models.R, e as funções de helpers.R, conforme a organização apresentada no início da Seção 3. O chunk anterior, prepare-cv-partition, lê a base produzida no pré-processamento (Seção 5.2.1) e disponibiliza a subamostra de calibração em calibration_data. Os dois ajustes utilizam esse objeto diretamente. A exportação utiliza a pasta Output/Results/Tables.
Procedimento
O bloco estima H0 e H1 na subamostra de calibração sob condições idênticas. Em seguida, organiza as cargas de cada ajuste e reúne os dois conjuntos em uma tabela unificada, identificando o modelo de origem de cada linha.
A função table_par() recebe cada ajuste e prepara sua tabela de parâmetros. Com lang = "pt", utiliza rótulos em português e mantém a seleção padrão de cargas livres. A rotina auxiliar tidy_par() preserva os parâmetros numéricos completos. O atributo table_data reúne as estimativas para apresentação em tela e exportação, enquanto par_data retém os parâmetros numéricos com precisão completa. Antes de combinar as tabelas, o código verifica se os dados de apresentação estão disponíveis e íntegros. A exportação reproduz os mesmos rótulos, ordem e valores de exibição em formato CSV compatível com o Excel.
Execução e resultado
Após a preparação indicada, execute o bloco completo. Ele gera a tabela apresentada acima, preserva os ajustes fit_analyzemodel e fit_h1modelfree na sessão e salva tbl-estimation-parameters.csv em Output/Results/Tables.
Código
# Estimate H0 using MLR/FIML and unit latent variances.fit_analyzemodel<-lavaan::cfa( model =analyzemodel, data =calibration_data, estimator ="MLR", missing ="fiml", std.lv =TRUE)# Estimate H1 under the same analytical conditions.fit_h1modelfree<-lavaan::cfa( model =h1modelfree, data =calibration_data, estimator ="MLR", missing ="fiml", std.lv =TRUE)# Prepare each model's formatted loading table.parameter_table_h0<-table_par(fit_analyzemodel, lang ="pt")parameter_table_h1<-table_par(fit_h1modelfree, lang ="pt")# Validate the display data before combining and exporting the tables.parameter_display_h0<-attr(parameter_table_h0, "table_data")parameter_display_h1<-attr(parameter_table_h1, "table_data")if(!is.data.frame(parameter_display_h0)||!is.data.frame(parameter_display_h1)||nrow(parameter_display_h0)==0L||nrow(parameter_display_h1)==0L){stop("table_data is missing. Reload helpers.R and rerun this chunk.")}# Stack H0 first and H1 second, identifying the model for every loading.parameter_estimates<-dplyr::bind_rows( H0 =parameter_display_h0, H1 =parameter_display_h1, .id ="Modelo")# Export exactly the content displayed in the combined table.readr::write_excel_csv2(parameter_estimates,here::here("Output", "Results", "Tables", "tbl-estimation-parameters.csv"), na ="NA")# Present the two model blocks in one table.knitr::kable(parameter_estimates, align =c("l", "l", "r", "r", "r", "r"), row.names =FALSE)
6.3 Convergência e admissibilidade
A verificação de convergência e admissibilidade encerra formalmente a etapa de estimação. A convergência atesta que o algoritmo encontrou uma solução estável para o modelo especificado. A admissibilidade matemática, por sua vez, é avaliada pela ausência de variâncias residuais negativas (casos Heywood) e de cargas padronizadas superiores à unidade (Brown, 2015; Nye, 2022). A Tabela 6.2 sintetiza essas verificações para H0 e H1, registrando o tamanho amostral efetivo e o número de parâmetros livres.
Na subamostra de calibração, ambos os modelos convergiram satisfatoriamente, sem apresentar estimativas impróprias de variância nem cargas padronizadas superiores a 1. As soluções mostram-se matematicamente admissíveis e aptas para as avaliações de ajuste global e local.
Tabela 6.2: Verificações de convergência e admissibilidade das soluções estimadas.
Atestar a convergência e a admissibilidade paramétrica dos dois modelos estimados, sumarizando o tamanho amostral e o número de parâmetros livres.
Preparação
Utilizam-se fit_analyzemodel e fit_h1modelfree, estimados no bloco da Tabela 6.1.
Procedimento
A lista diagnostic_fits viabiliza a inspeção padronizada de ambos os modelos. Para cada ajuste, o código recupera o status de convergência e o número de observações, calcula os parâmetros livres e examina variâncias e cargas padronizadas. As contagens registram variâncias negativas e cargas padronizadas maiores que 1.
O objeto estimation_checks reúne uma linha por modelo. A tabela apresentada e o CSV derivam do mesmo objeto, mantendo uma cópia dos diagnósticos para auditoria.
Execução e resultado
Execute o bloco para apresentar e salvar tbl-estimation-checks.csv em Output/Results/Tables, utilizando os ajustes existentes.
Código
# Collect the fitted models for diagnostic checks.diagnostic_fits<-list( H0 =fit_analyzemodel, H1 =fit_h1modelfree)# Check convergence and admissibility for each fitted model.estimation_checks<-purrr::imap_dfr(diagnostic_fits,function(fit, model_name){# Identify the freely estimated parameters.parameter_table<-lavaan::parTable(fit)free_parameters<-parameter_table|>dplyr::filter(free>0)# Extract the estimated variances.variance_table<-lavaan::parameterEstimates(fit)|>dplyr::filter(op=="~~", lhs==rhs)# Extract the standardized factor loadings.standardized_loadings<-lavaan::standardizedSolution(fit)|>dplyr::filter(op=="=~")# Count improper estimates and check convergence.negative_variances<-sum(variance_table$est<0, na.rm =TRUE)heywood_loadings<-sum(abs(standardized_loadings$est.std)>1, na.rm =TRUE)converged<-isTRUE(lavaan::lavInspect(fit, "converged"))# Summarize the diagnostic checks for the current model.tibble::tibble( Modelo =model_name, `N observado` =as.integer(lavaan::lavInspect(fit, "nobs")), `Parâmetros livres` =sum(free_parameters$free>0), Convergência =if(converged)"Sim"else"Não", `Variâncias negativas` =negative_variances, `Cargas padronizadas > 1` =heywood_loadings)})# Save the convergence and admissibility checks.write.csv2(estimation_checks,here::here("Output", "Results", "Tables", "tbl-estimation-checks.csv"), row.names =FALSE, na ="NA")# Present the convergence and admissibility checks.estimation_checks|>knitr::kable()
Brown, T. A. (2015). Confirmatory Factor Analysis for Applied Research. The Guilford Press.
Brown, T. A. (2023). Confirmatory Factor Analysis. Em R. H. Hoyle (Org.), Handbook of Structural Equation Modeling. The Guilford Press.
Jackson, D. L., Gillaspy, J. A., & Purc-Stephenson, R. (2009). Reporting Practices in Confirmatory Factor Analysis: An Overview and Some Recommendations. Psychological Methods, 14(1). https://doi.org/10.1037/a0014694
Kline, R. B. (2023). Principles and Pratice of Structural Equation Modeling (Fifth Edition). The Guilford Press.
Rhemtulla, M., Brosseau-Liard, P. É., & Savalei, V. (2012). When Can Categorical Variables Be Treated as Continuous? A Comparison of Robust Continuous and Categorical SEM Estimation Methods under Suboptimal Conditions. Psychological Methods, 17(3), 354–373. https://doi.org/10.1037/a0029315
Robitzsch, A. (2020). Why Ordinal Variables Can (Almost) Always Be Treated as Continuous Variables: Clarifying Assumptions of Robust Continuous and Ordinal Factor Analysis Estimation Methods. Frontiers in Education, 5. https://doi.org/10.3389/feduc.2020.589965
Robitzsch, A. (2022). On the Bias in Confirmatory Factor Analysis When Treating Discrete Variables as Ordinal Instead of Continuous. Axioms, 11(4). https://doi.org/10.3390/axioms11040162
Rogers, P. (2024). Best Practices for Your Confirmatory Factor Analysis: A JASP and Lavaan Tutorial. Behavior Research Methods. https://doi.org/10.3758/s13428-024-02375-7