6  Processo de estimação

O capítulo utiliza os scripts locais models.R e helpers.R, além da base whoqol_analysis.csv. Os modelos empíricos são os objetos analyzemodel e h1modelfree, definidos em models.R. O primeiro corresponde ao H0, com quatro fatores correlacionados e a covariância residual entre Q3 e Q4. O segundo corresponde ao H1 e acrescenta os três cross-loadings previamente justificados: Q8 e Q9 em psycho, e Q15 em environment.

Código
source(here::here("Scripts", "DataAppendixScripts", "models.R"))
source(here::here("Scripts", "DataAppendixScripts", "helpers.R"))

Depois da seleção dos modelos e do pré-processamento, esta seção estima as duas especificações da AFC na amostra de análise final. A estimação converte as relações previstas nos modelos em parâmetros amostrais e aplica as condições definidas nas etapas anteriores: tratamento contínuo dos itens, MLR, FIML e identificação pela variância dos fatores (Jackson et al., 2009; Nye, 2022).

6.1 Fundamentação da estimação

Os itens foram tratados como variáveis contínuas, conforme a justificativa desenvolvida na Seção 2.4. Segundo Rhemtulla et al. (2012), a MLR apresenta desempenho adequado em condições com cinco ou mais categorias, especialmente com limiares aproximadamente simétricos. Robitzsch (2020) e Robitzsch (2022) mostram que as abordagens contínua e ordinal definem alvos paramétricos distintos. Com cinco categorias e uma estrutura fatorial previamente definida, este estudo adota a formulação contínua como aproximação de mensuração.

O método MLR foi mantido porque combina a máxima verossimilhança com erros-padrão robustos e estatística de teste escalada. Essa combinação é adequada às distribuições observadas na etapa de pré-processamento e segue a recomendação da literatura para situações de não normalidade multivariada (Brown, 2015; Kline, 2023; Rogers, 2024).

As poucas respostas ausentes foram incorporadas por FIML. O procedimento utiliza a informação observada de cada participante e mantém os 1.243 casos da amostra analítica. A escolha segue a recomendação de tratar ausências na etapa de estimação quando se trabalha com ML ou suas variantes robustas (Brown, 2023; Kline, 2023).

A escala dos fatores foi definida pela fixação de suas variâncias em 1. Essa identificação permite estimar livremente as cargas fatoriais e estabelece a mesma métrica latente nos dois modelos. As duas especificações foram estimadas na mesma amostra e sob as mesmas condições. A comparação concentra-se, assim, nas três relações adicionais do modelo H1(Jackson et al., 2009; Nye, 2022).

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 reúne a carga não padronizada, o erro-padrão robusto, a estatística de teste e a carga padronizada, conforme recomendado por Jackson et al. (2009) e Nye (2022).

As cargas não padronizadas preservam a métrica do modelo. As cargas padronizadas permitem comparar a magnitude das relações dentro de cada especificação, e os erros-padrão refletem a inferência robusta do MLR.

A tabela inclui os dois modelos e mostra as três relações adicionais do H1 junto das cargas primárias. A avaliação dessas relações combina os parâmetros estimados com os índices de ajuste e os critérios de comparação dos modelos.

Tabela 6.1: Parâmetros fatoriais estimados nos modelos H0 e H1.
Modelo Fator Item Carga Erro-padrão z Carga padronizada
H0 psycho Q5 0.542 0.023 23.989 0.663
H0 psycho Q6 0.620 0.028 22.061 0.636
H0 psycho Q7 0.556 0.023 24.291 0.648
H0 psycho Q11 0.609 0.028 21.676 0.612
H0 psycho Q19 0.772 0.022 35.762 0.820
H0 psycho Q26 0.541 0.028 19.157 0.581
H0 physical Q3 0.395 0.030 13.150 0.420
H0 physical Q4 0.387 0.032 12.025 0.384
H0 physical Q10 0.650 0.023 28.113 0.720
H0 physical Q15 0.380 0.028 13.513 0.471
H0 physical Q16 0.559 0.028 19.973 0.541
H0 physical Q17 0.819 0.020 40.897 0.890
H0 physical Q18 0.802 0.023 35.540 0.840
H0 social Q20 0.708 0.023 30.520 0.795
H0 social Q21 0.513 0.030 17.008 0.509
H0 social Q22 0.637 0.025 25.597 0.721
H0 environment Q8 0.466 0.029 15.915 0.477
H0 environment Q9 0.504 0.027 18.719 0.570
H0 environment Q12 0.758 0.029 26.024 0.690
H0 environment Q13 0.507 0.027 18.649 0.613
H0 environment Q14 0.648 0.027 23.623 0.678
H0 environment Q23 0.485 0.029 16.894 0.511
H0 environment Q24 0.465 0.031 15.090 0.483
H0 environment Q25 0.492 0.031 16.075 0.503
H1 psycho Q5 0.541 0.023 23.884 0.662
H1 psycho Q6 0.621 0.028 22.037 0.638
H1 psycho Q7 0.558 0.023 24.251 0.650
H1 psycho Q11 0.609 0.028 21.691 0.612
H1 psycho Q19 0.773 0.022 35.835 0.822
H1 psycho Q26 0.541 0.028 19.167 0.582
H1 psycho Q8 0.160 0.049 3.263 0.163
H1 psycho Q9 0.108 0.043 2.512 0.122
H1 physical Q3 0.388 0.030 12.960 0.413
H1 physical Q4 0.382 0.032 11.849 0.378
H1 physical Q10 0.644 0.023 27.504 0.713
H1 physical Q15 0.221 0.032 6.839 0.274
H1 physical Q16 0.558 0.028 19.818 0.540
H1 physical Q17 0.826 0.020 42.158 0.897
H1 physical Q18 0.807 0.022 36.559 0.845
H1 social Q20 0.709 0.023 30.508 0.796
H1 social Q21 0.513 0.030 17.005 0.509
H1 social Q22 0.637 0.025 25.560 0.721
H1 environment Q8 0.329 0.050 6.559 0.336
H1 environment Q9 0.410 0.045 9.187 0.464
H1 environment Q12 0.769 0.029 26.536 0.700
H1 environment Q13 0.516 0.027 18.977 0.624
H1 environment Q14 0.656 0.028 23.846 0.687
H1 environment Q23 0.482 0.029 16.694 0.509
H1 environment Q24 0.470 0.031 15.098 0.488
H1 environment Q25 0.497 0.031 15.953 0.508
H1 environment Q15 0.257 0.033 7.851 0.319

O primeiro bloco lê a base analítica produzida no capítulo de pré-processamento. Em seguida, lavaan::cfa() ajusta os objetos analyzemodel e h1modelfree com máxima verossimilhança robusta (MLR), informação completa (FIML) para as ausências e identificação por variâncias latentes fixadas. Como os dois ajustes usam a mesma base e os mesmos argumentos, a diferença entre eles permanece restrita à especificação das cargas cruzadas.

lavaan::parameterEstimates(..., standardized = TRUE) reúne as estimativas não padronizadas, os erros-padrão robustos, as estatísticas de teste e as soluções padronizadas. O filtro op == "=~" mantém somente as relações de carga fatorial; variâncias, covariâncias fatoriais e variâncias residuais serão examinadas nas etapas apropriadas. A coluna std.all fornece a carga padronizada, enquanto est, se e z preservam, respectivamente, a carga na escala do ajuste, sua incerteza e a estatística de teste.

As tabelas específicas de H0 e H1 são combinadas por dplyr::bind_rows() e recebem a coluna Modelo, o que permite apresentar os resultados lado a lado sem repetir a mesma tabela no texto. write.csv2() salva a versão completa, com a precisão original, em Output/Results/Tables; essa exportação é útil para auditoria e reutilização independente da renderização. Na saída exibida, dplyr::mutate() arredonda apenas uma cópia destinada à apresentação, sem alterar o arquivo salvo. Por fim, knitr::kable() transforma essa cópia em uma tabela formatada para o HTML e o PDF.

Código
analysis_data <- readr::read_csv2(
  here::here("Data", "AnalysisData", "whoqol_analysis.csv"),
  na = c("", "NA"),
  show_col_types = FALSE
)

fit_analyzemodel <- lavaan::cfa(
  model = analyzemodel,
  data = analysis_data,
  estimator = "MLR",
  missing = "fiml",
  std.lv = TRUE
)

fit_h1modelfree <- lavaan::cfa(
  model = h1modelfree,
  data = analysis_data,
  estimator = "MLR",
  missing = "fiml",
  std.lv = TRUE
)

parameter_estimates_analyzemodel <- lavaan::parameterEstimates(
  fit_analyzemodel,
  standardized = TRUE
) |>
  dplyr::filter(op == "=~") |>
  dplyr::transmute(
    Modelo = "H~0~",
    Fator = lhs,
    Item = rhs,
    Carga = est,
    `Erro-padrão` = se,
        z = z,
    `Carga padronizada` = std.all
  )

parameter_estimates_h1modelfree <- lavaan::parameterEstimates(
  fit_h1modelfree,
  standardized = TRUE
) |>
  dplyr::filter(op == "=~") |>
  dplyr::transmute(
    Modelo = "H~1~",
    Fator = lhs,
    Item = rhs,
    Carga = est,
    `Erro-padrão` = se,
        z = z,
    `Carga padronizada` = std.all
  )

parameter_estimates <- dplyr::bind_rows(
  parameter_estimates_analyzemodel,
  parameter_estimates_h1modelfree
)

write.csv2(
  parameter_estimates,
  here::here("Output", "Results", "Tables", "tbl-estimation-parameters.csv"),
  row.names = FALSE,
  na = "NA"
)

parameter_estimates |>
  dplyr::mutate(
    dplyr::across(
      c(Carga, `Erro-padrão`, z, `Carga padronizada`),
      ~ round(.x, 3)
    )
  ) |>
  knitr::kable(escape = FALSE)

6.3 Convergência e admissibilidade

Convergência e admissibilidade encerram a etapa de estimação. A convergência indica que o algoritmo encontrou uma solução para o modelo especificado. A admissibilidade é examinada pelas variâncias negativas e pelas cargas padronizadas superiores a 1, diagnósticos associados a soluções Heywood (Brown, 2015; Nye, 2022). A Tabela 6.2 reúne essas verificações para H0 e H1 e registra o tamanho amostral e o número de parâmetros livres.

Os dois modelos convergiram, não apresentaram variâncias negativas e não produziram cargas padronizadas superiores a 1. As soluções estão prontas para a avaliação do ajuste global e local.

Tabela 6.2: Verificações de convergência e admissibilidade das soluções estimadas.
Modelo N observado Parâmetros livres Convergência Variâncias negativas Cargas padronizadas > 1
H0 1243 79 TRUE 0 0
H1 1243 82 TRUE 0 0

lavInspect(fit, "converged") identifica se o algoritmo terminou com uma solução convergida. A tabela de parâmetros é inspecionada para localizar variâncias negativas e cargas padronizadas maiores que 1, que podem caracterizar soluções Heywood. O número de parâmetros livres é recuperado para documentar a complexidade estimada de cada especificação.

O objeto diagnostic_fits apenas reúne os dois ajustes já estimados para que a mesma sequência de inspeções seja aplicada a H0 e H1; ele não realiza uma nova estimação. lavaan::parTable() fornece a coluna free, que permite contar os parâmetros efetivamente estimados, enquanto lavaan::lavInspect(..., "nobs") recupera o tamanho amostral utilizado pelo ajuste e lavaan::lavInspect(..., "converged") informa se o algoritmo convergiu.

As variâncias são obtidas com lavaan::parameterEstimates() filtrando as relações de variância (op == "~~" e lhs == rhs). As cargas padronizadas são recuperadas com lavaan::standardizedSolution() e filtradas para as relações de carga (op == "=~"). A contagem de valores negativos e de cargas maiores que 1 resume os dois diagnósticos de admissibilidade apresentados na tabela.

Depois dessas operações, tibble::tibble() organiza uma linha para cada modelo e somente as seis colunas relevantes para esta etapa. write.csv2() salva essa tabela diagnóstica em Output/Results/Tables/tbl-estimation-checks.csv, preservando uma cópia tabular para auditoria. A chamada final a knitr::kable() apresenta o mesmo objeto no HTML e no PDF; portanto, a tabela exibida e o CSV derivam da mesma estrutura, sem uma reconstrução posterior do resultado.

Código
diagnostic_fits <- list(
  H0 = fit_analyzemodel,
  H1 = fit_h1modelfree
)

estimation_checks <- purrr::imap_dfr(
  diagnostic_fits,
  function(fit, model_name) {
    parameter_table <- lavaan::parTable(fit)
    free_parameters <- parameter_table |>
      dplyr::filter(free > 0)

    variance_table <- lavaan::parameterEstimates(fit) |>
      dplyr::filter(op == "~~", lhs == rhs)

    standardized_loadings <- lavaan::standardizedSolution(fit) |>
      dplyr::filter(op == "=~")

    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"))

    tibble::tibble(
      Modelo = model_name,
      `N observado` = as.integer(lavaan::lavInspect(fit, "nobs")),
      `Parâmetros livres` = sum(free_parameters$free > 0),
      Convergência = converged,
      `Variâncias negativas` = negative_variances,
      `Cargas padronizadas > 1` = heywood_loadings
    )
  }
)

write.csv2(
  estimation_checks,
  here::here("Output", "Results", "Tables", "tbl-estimation-checks.csv"),
  row.names = FALSE,
  na = "NA"
)

estimation_checks |>
  knitr::kable()