Relatório Técnico-Estatístico: 3ª Etapa — Validação Clínica

Modelagem da Estrutura Latente dos Fatores de Risco via TRI (Modelo 2PL) e Análise de Classes Latentes (LCA)

Data de Publicação

9 de novembro de 2026

1 Introdução e Escopo Metodológico

Este documento apresenta os resultados da validação clínica baseada na estrutura latente do bloco III — Fatores de Risco (\(n = 215\) participantes; 24 itens avaliados do número 19 ao 41), na ausência de um padrão-ouro externo. O protocolo analítico estrutura-se em três etapas:

  1. Consistência Interna e Polaridade Semântica: Avaliação pelo coeficiente KR-20 (Kuder-Richardson) e Ômega de McDonald (\(\omega\)) sobre matriz tetracórica, corrigindo a direção dos itens protetores.
  2. Teoria de Resposta ao Item (TRI — Modelo Logístico de 2 Parâmetros [2PL]): Estimação do poder discriminativo (\(a_j\)) e do limiar de gravidade/dificuldade (\(b_j\)) de cada fator ao longo do traço latente contínuo de vulnerabilidade ocupacional (\(\theta\)).
  3. Análise de Classes Latentes (LCA) e Acurácia Diagnóstica: Identificação de agrupamentos diagnósticos naturais (\(K = 2\) e \(K = 3\) classes) via algoritmo Expectation-Maximization (EM) para extrair Sensibilidade (\(Se\)), Especificidade (\(Es\)), Valor Preditivo Positivo (\(VPP\)), Valor Preditivo Negativo (\(VPN\)) e Índice \(J\) de Youden, seguida de comparação inferencial entre classes via gtsummary.
Código
# Instalação automática de pacotes ausentes
pacotes <- c("readxl", "dplyr", "tidyr", "stringr", "ggplot2", "purrr",
             "psych", "mirt", "poLCA", "flextable", "gtsummary")

novos_pacotes <- pacotes[!(pacotes %in% installed.packages()[, "Package"])]
if (length(novos_pacotes) > 0) install.packages(novos_pacotes)

library(readxl)
library(dplyr)
library(tidyr)
library(stringr)
library(ggplot2)
library(purrr)
library(psych)
library(mirt)
library(poLCA)
library(flextable)
library(gtsummary)

# Configuração global de idioma e formatação decimal (vírgula) no gtsummary
theme_gtsummary_language(language = "pt", decimal.mark = ",", big.mark = ".")
theme_gtsummary_compact()

# Configuração global do flextable para renderização em HTML
set_flextable_defaults(
  font.family = "Arial",
  font.size = 10,
  theme_fun = theme_booktabs,
  padding.top = 5,
  padding.bottom = 5,
  padding.left = 6,
  padding.right = 6,
  decimal.mark = ",",
  big.mark = ".",
  na_str = "—"
)

# Função auxiliar para formatar tabelas flextable em HTML
formatar_ft_html <- function(ft, titulo = NULL, nota_rodape = NULL) {
  ft <- ft %>%
    theme_booktabs() %>%
    bold(part = "header") %>%
    valign(valign = "center", part = "all") %>%
    autofit()
  
  if (!is.null(titulo)) {
    ft <- set_caption(ft, caption = titulo)
  }
  if (!is.null(nota_rodape)) {
    ft <- add_footer_lines(ft, values = nota_rodape) %>%
      fontsize(size = 9, part = "footer") %>%
      italic(part = "footer")
  }
  return(ft)
}

theme_set(theme_minimal(base_size = 12))

2 Auditoria de Dados e Tratamento de Polaridade

Código
# 1. Leitura da planilha (cabeçalho na linha 2) e remoção de espaços extras nos nomes das colunas
df_bruto <- read_excel("COLETA_DADOS_ETAPA_3.xlsx", sheet = "III-FATORES RISCO", skip = 1) %>%
  rename_with(str_trim)

# 2. Tabela 1: Auditoria de pulo lógico (Itens 21 e 21.1) via gtsummary -> flextable
df_pulo <- df_bruto %>%
  transmute(
    turno_noturno = factor(str_trim(`21. TRABALHA TURNO NOTURNO`), levels = c("SIM", "NÃO")),
    afeta_descanso = factor(str_trim(`21.1 AFETA DESCANSO`), levels = c("SIM", "NÃO", "NÃO SE APLICA"))
  )

tbl_pulo <- df_pulo %>%
  tbl_cross(
    row = turno_noturno,
    col = afeta_descanso,
    percent = "row",
    label = list(
      turno_noturno ~ "21. Trabalha em turno noturno",
      afeta_descanso ~ "21.1. O turno noturno afeta o descanso?"
    ),
    margin_text = "Total"
  ) %>%
  bold_labels() %>%
  as_flex_table() %>%
  formatar_ft_html(
    titulo = "Tabela 1. Auditoria de consistência e pulo lógico entre o trabalho em turno noturno (item 21) e o prejuízo no descanso (item 21.1) (n = 215).",
    nota_rodape = "Nota: Valores expressos em frequência absoluta (n) e percentual na linha (%). Observam-se 3 casos com resposta preenchida no item 21.1 entre não trabalhadores noturnos."
  )

tbl_pulo

21.1. O turno noturno afeta o descanso?

SIM

NÃO

NÃO SE APLICA

Total

21. Trabalha em turno noturno

—

—

—

—

SIM

66 (71%)

27 (29%)

0 (0%)

93 (100%)

NÃO

1 (0,8%)

2 (1,6%)

119 (98%)

122 (100%)

Total

67 (31%)

29 (13%)

119 (55%)

215 (100%)

Nota: Valores expressos em frequência absoluta (n) e percentual na linha (%). Observam-se 3 casos com resposta preenchida no item 21.1 entre não trabalhadores noturnos.

Código
# 3. Codificação binária (SIM = 1, NÃO = 0) nos 23 itens independentes
df_bin <- df_bruto %>%
  select(-ORDEM, -`21.1 AFETA DESCANSO`) %>%
  mutate(across(everything(), ~ ifelse(str_trim(.) == "SIM", 1, 0)))

# 4. Inversão dos 4 itens de formulação protetora (1 = Presença de Fator de Risco)
itens_protetores <- c(
  "22. FUXO TRABALHO", 
  "29.AUTONOMIA PROFISSIONAL", 
  "32.APOIO CHEFIA", 
  "33.APOIO DOS COLEGAS"
)

df_risco <- df_bin %>%
  mutate(across(all_of(itens_protetores), ~ 1 - .))

# Dicionário de rótulos padronizados
rotulos_itens <- c(
  "19. SENTE DIFICULDADE TOMAR DECISÕES"        = "19. Dificuldade em tomar decisões",
  "20.PRESSÕES EMOCIONAIS"                      = "20. Pressões emocionais",
  "21. TRABALHA TURNO NOTURNO"                  = "21. Trabalha em turno noturno",
  "22. FUXO TRABALHO"                           = "22. Fluxo de trabalho inadequado*",
  "23. DESORGANIZAÇÃO ROTINA AMBIENTE TRABALHO" = "23. Desorganização da rotina",
  "24.TRATAMENTO DIFERENTE GÊNERO"              = "24. Tratamento diferente por gênero",
  "25.QUANTIDADE TAREFAS"                       = "25. Excesso de tarefas",
  "26.TEMPO ATUAÇÃO < 5 ANOS"                   = "26. Tempo de atuação < 5 anos",
  "27.FALTA DE CLAREZA"                         = "27. Falta de clareza nas atribuições",
  "28.VIOLÊNCIA FÍSICA OU VERBAL"               = "28. Violência física ou verbal",
  "29.AUTONOMIA PROFISSIONAL"                   = "29. Falta de autonomia profissional*",
  "30.DESENTENDIMENTOS COLEGAS"                 = "30. Desentendimentos com colegas",
  "31.PRESSÃO NO TRABALHO"                      = "31. Pressão no trabalho",
  "32.APOIO CHEFIA"                             = "32. Falta de apoio da chefia*",
  "33.APOIO DOS COLEGAS"                        = "33. Falta de apoio dos colegas*",
  "34.FALTA CAPACITAÇÃO"                        = "34. Falta de capacitação",
  "35.AMBIENTE INSALUBRE"                       = "35. Ambiente insalubre",
  "36.PACIENTES ESTADO CRÍTICO"                 = "36. Assistência a pacientes críticos",
  "37.FALTA DE MATERIAIS"                       = "37. Falta de materiais",
  "38.FALTA RECURSOS HUMANOS"                   = "38. Falta de recursos humanos",
  "39.SISTEMAS DIGITAIS"                        = "39. Dificuldades com sistemas digitais",
  "40.INJUSTIÇA NO TRABALHO"                    = "40. Injustiça no trabalho",
  "41.FALHAS COMUNICAÇÃO"                       = "41. Falhas na comunicação"
)

2.1 Interpretação da Qualidade dos Dados

  • Pulo Lógico Condicional (Itens 21 e 21.1): Dos \(93\) participantes que trabalham em turno noturno (\(43,26\%\)), \(70,97\%\) (\(n = 66\)) relataram prejuízo no descanso. Como o item 21.1 é estruturalmente dependente do item 21, sua inclusão simultânea nos modelos de TRI e LCA violaria o pressuposto de independência condicional local (gerando um doublet artificial). Por isso, os modelos multivariados são estimados sobre os 23 fatores independentes, reportando-se o item 21.1 como indicador condicional específico do subgrupo noturno.
  • Efeito Teto (Ceiling Effect): Os fatores 38. Falta de recursos humanos (\(95,35\%\), \(\text{DP} = 0,2111\)) e 41. Falhas na comunicação (\(93,49\%\), \(\text{DP} = 0,2473\)) são quase onipresentes na amostra, configurando estressores estruturais basais do ambiente avaliado.

3 Estatísticas Descritivas e Consistência Interna (KR-20)

Código
escore_bruto <- rowSums(df_bin)
escore_risco <- rowSums(df_risco)

k <- ncol(df_risco)
kr20_bruto <- (k / (k - 1)) * (1 - sum(apply(df_bin, 2, var)) / var(escore_bruto))
kr20_risco <- (k / (k - 1)) * (1 - sum(apply(df_risco, 2, var)) / var(escore_risco))

resumo_escores <- tibble(
  Configuracao = c("Matriz Original (Sem Inversão)", "Matriz Corrigida (Itens 22, 29, 32 e 33 Invertidos)"),
  N = c(nrow(df_bin), nrow(df_risco)),
  KR_20 = c(kr20_bruto, kr20_risco),
  Media_DP = c(sprintf("%.2f (%.2f)", mean(escore_bruto), sd(escore_bruto)),
               sprintf("%.2f (%.2f)", mean(escore_risco), sd(escore_risco))),
  Mediana_IIQ = c(sprintf("%.1f (%.1f)", median(escore_bruto), IQR(escore_bruto)),
                  sprintf("%.1f (%.1f)", median(escore_risco), IQR(escore_risco))),
  Min_Max = c(sprintf("%d – %d", min(escore_bruto), max(escore_bruto)),
              sprintf("%d – %d", min(escore_risco), max(escore_risco)))
) %>%
  mutate(across(c(Media_DP, Mediana_IIQ), ~ str_replace_all(., "\\.", ",")))

ft_tab2 <- flextable(resumo_escores) %>%
  set_header_labels(
    Configuracao = "Parametrização da Escala",
    N = "n",
    KR_20 = "KR-20",
    Media_DP = "Média (DP)",
    Mediana_IIQ = "Mediana (IIQ)",
    Min_Max = "Mín – Máx"
  ) %>%
  colformat_double(j = "KR_20", digits = 4, decimal.mark = ",") %>%
  align(j = 2:6, align = "center", part = "all") %>%
  formatar_ft_html(
    titulo = "Tabela 2. Comparação da consistência interna (Kuder-Richardson KR-20) e distribuição do escore total antes e após a inversão dos itens protetores (n = 215).",
    nota_rodape = "Legenda: KR-20 = Coeficiente de Kuder-Richardson de 20 itens; DP = Desvio-Padrão; IIQ = Intervalo Interquartil."
  )

ft_tab2

Parametrização da Escala

n

KR-20

Média (DP)

Mediana (IIQ)

Mín – Máx

Matriz Original (Sem Inversão)

215

0,5192

14,78 (2,91)

15,0 (4,0)

6 – 21

Matriz Corrigida (Itens 22, 29, 32 e 33 Invertidos)

215

0,7555

12,48 (3,92)

13,0 (5,0)

2 – 21

Legenda: KR-20 = Coeficiente de Kuder-Richardson de 20 itens; DP = Desvio-Padrão; IIQ = Intervalo Interquartil.

Código
tab_desc_itens <- tibble(
  Variavel = names(df_risco),
  Item = unname(rotulos_itens[names(df_risco)]),
  n_Risco = colSums(df_risco),
  Prev_Pct = colMeans(df_risco) * 100,
  Media = colMeans(df_risco),
  DP = apply(df_risco, 2, sd),
  Mediana = apply(df_risco, 2, median),
  Min_Max = "0 – 1",
  r_item_resto = map_dbl(names(df_risco), ~ cor(df_risco[[.x]], rowSums(df_risco[, setdiff(names(df_risco), .x)])))
) %>%
  arrange(desc(Prev_Pct)) %>%
  select(-Variavel)

ft_tab3 <- flextable(tab_desc_itens) %>%
  set_header_labels(
    Item = "Fator de Risco Avaliado",
    n_Risco = "n",
    Prev_Pct = "Prevalência (%)",
    Media = "Média",
    DP = "DP",
    Mediana = "Mediana",
    Min_Max = "Mín–Máx",
    r_item_resto = "r item-resto"
  ) %>%
  colformat_double(j = "Prev_Pct", digits = 2, decimal.mark = ",") %>%
  colformat_double(j = c("Media", "DP"), digits = 4, decimal.mark = ",") %>%
  colformat_double(j = "Mediana", digits = 1, decimal.mark = ",") %>%
  colformat_double(j = "r_item_resto", digits = 3, decimal.mark = ",") %>%
  align(j = 2:8, align = "center", part = "all") %>%
  formatar_ft_html(
    titulo = "Tabela 3. Estatísticas descritivas e correlações item-total corrigidas (r item-resto) dos 23 fatores de risco (n = 215).",
    nota_rodape = "*Nota: Itens 22, 29, 32 e 33 codificados de forma invertida (NÃO = 1 [presença do fator de risco por ausência do fator protetor]). DP = Desvio-Padrão."
  )

ft_tab3

Fator de Risco Avaliado

n

Prevalência (%)

Média

DP

Mediana

Mín–Máx

r item-resto

38. Falta de recursos humanos

205

95,35

0,9535

0,2111

1,0

0 – 1

0,225

41. Falhas na comunicação

201

93,49

0,9349

0,2473

1,0

0 – 1

0,174

35. Ambiente insalubre

187

86,98

0,8698

0,3373

1,0

0 – 1

0,295

37. Falta de materiais

181

84,19

0,8419

0,3657

1,0

0 – 1

0,254

20. Pressões emocionais

179

83,26

0,8326

0,3742

1,0

0 – 1

0,424

40. Injustiça no trabalho

159

73,95

0,7395

0,4399

1,0

0 – 1

0,443

28. Violência física ou verbal

154

71,63

0,7163

0,4519

1,0

0 – 1

0,364

27. Falta de clareza nas atribuições

146

67,91

0,6791

0,4679

1,0

0 – 1

0,334

25. Excesso de tarefas

142

66,05

0,6605

0,4747

1,0

0 – 1

0,387

26. Tempo de atuação < 5 anos

140

65,12

0,6512

0,4777

1,0

0 – 1

0,230

36. Assistência a pacientes críticos

137

63,72

0,6372

0,4819

1,0

0 – 1

0,185

34. Falta de capacitação

121

56,28

0,5628

0,4972

1,0

0 – 1

0,232

23. Desorganização da rotina

112

52,09

0,5209

0,5007

1,0

0 – 1

0,367

31. Pressão no trabalho

97

45,12

0,4512

0,4988

0,0

0 – 1

0,410

21. Trabalha em turno noturno

93

43,26

0,4326

0,4966

0,0

0 – 1

0,147

30. Desentendimentos com colegas

75

34,88

0,3488

0,4777

0,0

0 – 1

0,268

39. Dificuldades com sistemas digitais

71

33,02

0,3302

0,4714

0,0

0 – 1

0,264

29. Falta de autonomia profissional*

59

27,44

0,2744

0,4473

0,0

0 – 1

0,372

19. Dificuldade em tomar decisões

51

23,72

0,2372

0,4264

0,0

0 – 1

0,203

32. Falta de apoio da chefia*

50

23,26

0,2326

0,4234

0,0

0 – 1

0,398

24. Tratamento diferente por gênero

49

22,79

0,2279

0,4205

0,0

0 – 1

0,386

22. Fluxo de trabalho inadequado*

45

20,93

0,2093

0,4078

0,0

0 – 1

0,366

33. Falta de apoio dos colegas*

29

13,49

0,1349

0,3424

0,0

0 – 1

0,167

*Nota: Itens 22, 29, 32 e 33 codificados de forma invertida (NÃO = 1 [presença do fator de risco por ausência do fator protetor]). DP = Desvio-Padrão.

3.1 Interpretação da Consistência Interna

  • Na codificação original, os itens 22. Fluxo de trabalho (\(r_{it} = -0,369\)), 32. Apoio da chefia (\(r_{it} = -0,338\)), 29. Autonomia profissional (\(r_{it} = -0,295\)) e 33. Apoio dos colegas (\(r_{it} = -0,133\)) apresentavam correlações negativas com o escore total porque medem condições protetoras.
  • Após a inversão semântica desses quatro itens, o coeficiente KR-20 eleva-se de 0,5192 para 0,7555, superando o ponto de corte psicométrico de \(0,70\) e demonstrando consistência interna satisfatória (Escore de Risco Corrigido: \(\text{Média} = 12,48 \pm 3,92\); \(\text{Mediana} = 13,0\); \(\text{IIQ} = 5,0\); \(\text{Mín} = 2\); \(\text{Máx} = 21\)).

4 Calibração Psicométrica via Teoria de Resposta ao Item (TRI — 2PL)

Código
mod_2pl <- mirt(df_risco, model = 1, itemtype = "2PL", SE = TRUE, verbose = FALSE)

params_tri <- as.data.frame(coef(mod_2pl, IRTpars = TRUE, simplify = TRUE)$items) %>%
  mutate(
    Variavel = rownames(.),
    Item = unname(rotulos_itens[Variavel]),
    Prev_Risco = colMeans(df_risco) * 100,
    Classificacao_a = case_when(
      a >= 1.35 ~ "Muito Alta (a ≥ 1,35)",
      a >= 1.00 ~ "Alta (1,00 ≤ a < 1,35)",
      a >= 0.65 ~ "Moderada (0,65 ≤ a < 1,00)",
      TRUE      ~ "Baixa (a < 0,65)"
    )
  ) %>%
  select(Item, Prev_Risco, a, b, Classificacao_a) %>%
  arrange(desc(a))

ft_tab4 <- flextable(params_tri) %>%
  set_header_labels(
    Item = "Fator de Risco",
    Prev_Risco = "Prevalência (%)",
    a = "Discriminação (a)",
    b = "Gravidade / Limiar (b)",
    Classificacao_a = "Classificação Discriminativa (Baker)"
  ) %>%
  colformat_double(j = "Prev_Risco", digits = 2, decimal.mark = ",") %>%
  colformat_double(j = c("a", "b"), digits = 3, decimal.mark = ",") %>%
  align(j = 2:5, align = "center", part = "all") %>%
  bold(i = ~ a >= 1.00, j = c("Item", "a")) %>%
  formatar_ft_html(
    titulo = "Tabela 4. Parâmetros de discriminação (a) e gravidade/limiar clínico (b) estimados via Modelo Logístico de 2 Parâmetros (2PL) da TRI (n = 215).",
    nota_rodape = "Nota: Calibração por Máxima Verossimilhança Marginal (MML). Classificação de Baker (2001): Muito alta (a >= 1,35); Alta (1,00 a 1,34); Moderada (0,65 a 0,99); Baixa (< 0,65). Itens em negrito possuem alta capacidade de discriminação (a >= 1,00)."
  )

ft_tab4

Fator de Risco

Prevalência (%)

Discriminação (a)

Gravidade / Limiar (b)

Classificação Discriminativa (Baker)

20. Pressões emocionais

83,26

1,922

-1,296

Muito Alta (a ≥ 1,35)

32. Falta de apoio da chefia*

23,26

1,455

1,121

Muito Alta (a ≥ 1,35)

40. Injustiça no trabalho

73,95

1,445

-0,986

Muito Alta (a ≥ 1,35)

22. Fluxo de trabalho inadequado*

20,93

1,389

1,276

Muito Alta (a ≥ 1,35)

24. Tratamento diferente por gênero

22,79

1,343

1,199

Alta (1,00 ≤ a < 1,35)

38. Falta de recursos humanos

95,35

1,336

-2,820

Alta (1,00 ≤ a < 1,35)

31. Pressão no trabalho

45,12

1,311

0,200

Alta (1,00 ≤ a < 1,35)

25. Excesso de tarefas

66,05

1,271

-0,681

Alta (1,00 ≤ a < 1,35)

29. Falta de autonomia profissional*

27,44

1,199

1,030

Alta (1,00 ≤ a < 1,35)

28. Violência física ou verbal

71,63

1,186

-0,988

Alta (1,00 ≤ a < 1,35)

27. Falta de clareza nas atribuições

67,91

1,054

-0,867

Alta (1,00 ≤ a < 1,35)

23. Desorganização da rotina

52,09

1,050

-0,096

Alta (1,00 ≤ a < 1,35)

35. Ambiente insalubre

86,98

0,970

-2,284

Moderada (0,65 ≤ a < 1,00)

37. Falta de materiais

84,19

0,894

-2,147

Moderada (0,65 ≤ a < 1,00)

41. Falhas na comunicação

93,49

0,874

-3,413

Moderada (0,65 ≤ a < 1,00)

39. Dificuldades com sistemas digitais

33,02

0,717

1,097

Moderada (0,65 ≤ a < 1,00)

30. Desentendimentos com colegas

34,88

0,716

0,970

Moderada (0,65 ≤ a < 1,00)

19. Dificuldade em tomar decisões

23,72

0,680

1,884

Moderada (0,65 ≤ a < 1,00)

26. Tempo de atuação < 5 anos

65,12

0,624

-1,087

Baixa (a < 0,65)

34. Falta de capacitação

56,28

0,593

-0,460

Baixa (a < 0,65)

33. Falta de apoio dos colegas*

13,49

0,512

3,809

Baixa (a < 0,65)

36. Assistência a pacientes críticos

63,72

0,446

-1,320

Baixa (a < 0,65)

21. Trabalha em turno noturno

43,26

0,339

0,824

Baixa (a < 0,65)

Nota: Calibração por Máxima Verossimilhança Marginal (MML). Classificação de Baker (2001): Muito alta (a >= 1,35); Alta (1,00 a 1,34); Moderada (0,65 a 0,99); Baixa (< 0,65). Itens em negrito possuem alta capacidade de discriminação (a >= 1,00).

Código
# Extração do escore latente individual (Theta EAP)
escores_eap <- as.numeric(fscores(mod_2pl, method = "EAP"))
Código
ggplot(params_tri, aes(x = b, y = a, color = Classificacao_a)) +
  geom_hline(yintercept = 1.00, linetype = "dashed", color = "#1b9e77", alpha = 0.8) +
  geom_hline(yintercept = 0.65, linetype = "dotted", color = "#d95f02", alpha = 0.8) +
  geom_vline(xintercept = 0.00, linetype = "solid", color = "gray70") +
  geom_point(size = 3.5, alpha = 0.9) +
  geom_text(aes(label = Item), hjust = -0.05, vjust = 0.4, size = 3, show.legend = FALSE, check_overlap = TRUE) +
  scale_x_continuous(limits = c(-3.8, 4.8)) +
  scale_color_brewer(palette = "Dark2") +
  labs(
    title = "Figura 1. Mapa de Calibração da TRI (Modelo Logístico 2PL)",
    subtitle = "Limiar de Gravidade Clínica (b) versus Capacidade de Discriminação (a)",
    x = "Parâmetro de Gravidade / Dificuldade (b) em desvios-padrão do traço latente (θ)",
    y = "Parâmetro de Discriminação (a)",
    color = "Nível de Discriminação"
  ) +
  theme(legend.position = "bottom")

4.1 Interpretação Clínica da TRI

  1. Capacidade Discriminativa (\(a_j\)): Doze dos 23 itens apresentaram discriminação alta ou muito alta (\(a \ge 1,00\)), liderados por 20. Pressões emocionais (\(a = 1,922\)), 32. Falta de apoio da chefia (\(a = 1,455\)), 40. Injustiça no trabalho (\(a = 1,445\)), 22. Fluxo de trabalho inadequado (\(a = 1,390\)), 24. Tratamento diferente por gênero (\(a = 1,343\)), 38. Falta de RH (\(a = 1,337\)) e 31. Pressão no trabalho (\(a = 1,311\)).
  2. Espectro de Gravidade Clínica (\(b_j\)):
    • Estressores Estruturais Basais (\(b < -2,0\)): 41. Falhas na comunicação (\(b = -3,412\)), 38. Falta de RH (\(b = -2,820\)), 35. Ambiente insalubre (\(b = -2,284\)) e 37. Falta de materiais (\(b = -2,147\)) ocorrem mesmo em níveis muito baixos de vulnerabilidade latente.
    • Estressores Intermediários / Progressivos (\(-1,3 < b < +0,3\)): 20. Pressões emocionais (\(b = -1,296\)), 28. Violência (\(b = -0,988\)), 40. Injustiça (\(b = -0,986\)), 27. Falta de clareza (\(b = -0,867\)), 25. Excesso de tarefas (\(b = -0,681\)), 23. Desorganização da rotina (\(b = -0,096\)) e 31. Pressão no trabalho (\(b = +0,200\)) demarcam a transição clínica para o adoecimento/sobrecarga.
    • Marcadores de Descompensação Grave (\(b > +1,0\)): 29. Falta de autonomia (\(b = +1,031\)), 32. Falta de apoio da chefia (\(b = +1,121\)), 24. Tratamento diferente por gênero (\(b = +1,199\)), 22. Fluxo de trabalho inadequado (\(b = +1,276\)), 19. Dificuldade em tomar decisões (\(b = +1,884\)) e 33. Falta de apoio dos colegas (\(b = +3,809\)) exigem níveis severos do traço latente (\(\theta > +1,0\text{ DP}\)) para se manifestarem.

5 Análise de Classes Latentes (LCA) e Acurácia Diagnóstica

Código
df_lca <- df_risco %>%
  mutate(across(everything(), ~ as.integer(. + 1))) %>%
  rename_with(~ paste0("I", seq_along(.)))

formula_lca <- as.formula(paste("cbind(", paste(names(df_lca), collapse = ", "), ") ~ 1"))

ajustar_lca <- function(k, seed = 2026) {
  set.seed(seed)
  mod <- poLCA(formula_lca, data = df_lca, nclass = k, nrep = 40, maxiter = 3000, verbose = FALSE)
  n <- nrow(df_lca)
  p <- mod$npar
  ll <- mod$llik
  sabic <- -2 * ll + log((n + 2) / 24) * p
  
  if (k > 1) {
    post <- pmax(mod$posterior, 1e-10)
    entropia <- 1 - (-sum(post * log(post))) / (n * log(k))
  } else {
    entropia <- 1.000
  }
  
  ordem <- if (k > 1) order(rowMeans(sapply(mod$probs, function(m) m[, 2]))) else 1
  props_txt <- paste(sprintf("%.1f%%", mod$P[ordem] * 100), collapse = " | ") %>%
    str_replace_all("\\.", ",")
  
  list(modelo = mod, ordem = ordem, resumo = tibble(
    Classes_K = paste0(k, " Classe(s)"),
    LogLik = ll,
    Parametros = p,
    AIC = mod$aic,
    BIC = mod$bic,
    SABIC = sabic,
    Entropia = entropia,
    Proporcoes = props_txt
  ))
}

res_k1 <- ajustar_lca(1)
res_k2 <- ajustar_lca(2)
res_k3 <- ajustar_lca(3)
res_k4 <- ajustar_lca(4)

tab_ajuste_lca <- bind_rows(res_k1$resumo, res_k2$resumo, res_k3$resumo, res_k4$resumo)

ft_tab5 <- flextable(tab_ajuste_lca) %>%
  set_header_labels(
    Classes_K = "Modelo (K)",
    LogLik = "Log-Verossimilhança",
    Parametros = "Parâmetros",
    AIC = "AIC",
    BIC = "BIC",
    SABIC = "SABIC",
    Entropia = "Entropia (E)",
    Proporcoes = "Distribuição das Classes (%)"
  ) %>%
  colformat_double(j = c("LogLik", "AIC", "BIC", "SABIC"), digits = 2, decimal.mark = ",") %>%
  colformat_double(j = "Entropia", digits = 4, decimal.mark = ",") %>%
  align(j = 2:8, align = "center", part = "all") %>%
  bold(i = c(2, 3)) %>%
  formatar_ft_html(
    titulo = "Tabela 5. Critérios de informação e qualidade de classificação (Entropia) para seleção do número ótimo de classes latentes (n = 215).",
    nota_rodape = "Legenda: AIC = Critério de Informação de Akaike; BIC = Critério de Informação Bayesiano; SABIC = BIC ajustado pelo tamanho amostral. Modelos de 2 classes (menor BIC) e 3 classes (menor SABIC e Entropia > 0,80) destacados em negrito."
  )

ft_tab5

Modelo (K)

Log-Verossimilhança

Parâmetros

AIC

BIC

SABIC

Entropia (E)

Distribuição das Classes (%)

1 Classe(s)

-2.708,62

23

5.463,24

5.540,77

5.467,89

1,0000

100,0%

2 Classe(s)

-2.554,22

47

5.202,43

5.360,85

5.211,92

0,7441

43,7% | 56,3%

3 Classe(s)

-2.509,01

71

5.160,01

5.399,33

5.174,34

0,8084

14,5% | 57,3% | 28,2%

4 Classe(s)

-2.479,36

95

5.148,72

5.468,93

5.167,90

0,8477

17,9% | 47,6% | 10,7% | 23,8%

Legenda: AIC = Critério de Informação de Akaike; BIC = Critério de Informação Bayesiano; SABIC = BIC ajustado pelo tamanho amostral. Modelos de 2 classes (menor BIC) e 3 classes (menor SABIC e Entropia > 0,80) destacados em negrito.

Código
mod_k2 <- res_k2$modelo
prob_k2 <- sapply(mod_k2$probs, function(mat) mat[, 2])
ordem_k2 <- res_k2$ordem # [1] = Baixo Risco, [2] = Alto Risco

pi_baixo <- mod_k2$P[ordem_k2[1]]
pi_alto  <- mod_k2$P[ordem_k2[2]]

se_vec  <- prob_k2[ordem_k2[2], ]
es_vec  <- 1 - prob_k2[ordem_k2[1], ]
vpp_vec <- (se_vec * pi_alto) / (se_vec * pi_alto + (1 - es_vec) * pi_baixo)
vpn_vec <- (es_vec * pi_baixo) / (es_vec * pi_baixo + (1 - se_vec) * pi_alto)
youden  <- se_vec + es_vec - 1

n_alto  <- nrow(df_risco) * pi_alto
n_baixo <- nrow(df_risco) * pi_baixo

se_ic_inf <- pmax(0, se_vec - 1.96 * sqrt(se_vec * (1 - se_vec) / n_alto))
se_ic_sup <- pmin(1, se_vec + 1.96 * sqrt(se_vec * (1 - se_vec) / n_alto))
es_ic_inf <- pmax(0, es_vec - 1.96 * sqrt(es_vec * (1 - es_vec) / n_baixo))
es_ic_sup <- pmin(1, es_vec + 1.96 * sqrt(es_vec * (1 - es_vec) / n_baixo))

tab_acuracia <- tibble(
  Item = unname(rotulos_itens[names(df_risco)]),
  Se_Txt = str_replace_all(sprintf("%.2f (%.1f–%.1f)", se_vec * 100, se_ic_inf * 100, se_ic_sup * 100), "\\.", ","),
  Es_Txt = str_replace_all(sprintf("%.2f (%.1f–%.1f)", es_vec * 100, es_ic_inf * 100, es_ic_sup * 100), "\\.", ","),
  VPP_Pct = vpp_vec * 100,
  VPN_Pct = vpn_vec * 100,
  J_Youden = youden
) %>%
  arrange(desc(J_Youden))

ft_tab6 <- flextable(tab_acuracia) %>%
  set_header_labels(
    Item = "Fator de Risco Clínico",
    Se_Txt = "Sensibilidade % (IC 95%)",
    Es_Txt = "Especificidade % (IC 95%)",
    VPP_Pct = "VPP (%)",
    VPN_Pct = "VPN (%)",
    J_Youden = "Índice J de Youden"
  ) %>%
  colformat_double(j = c("VPP_Pct", "VPN_Pct"), digits = 2, decimal.mark = ",") %>%
  colformat_double(j = "J_Youden", digits = 3, decimal.mark = ",") %>%
  align(j = 2:6, align = "center", part = "all") %>%
  bold(i = ~ J_Youden >= 0.300, j = c("Item", "J_Youden")) %>%
  formatar_ft_html(
    titulo = "Tabela 6. Medidas de acurácia diagnóstica clínica dos 23 fatores de risco estimadas via Análise de Classes Latentes (K = 2 classes; n = 215).",
    nota_rodape = "Legenda: IC 95% = Intervalo de Confiança de 95%; VPP = Valor Preditivo Positivo; VPN = Valor Preditivo Negativo; Índice J de Youden = Se + Es - 1. Prevalência da classe latente de Alto Risco Clínico = 56,3%."
  )

ft_tab6

Fator de Risco Clínico

Sensibilidade % (IC 95%)

Especificidade % (IC 95%)

VPP (%)

VPN (%)

Índice J de Youden

31. Pressão no trabalho

66,54 (58,1–74,9)

82,49 (74,8–90,2)

83,04

65,67

0,490

25. Excesso de tarefas

84,44 (78,0–90,9)

57,66 (47,7–67,7)

71,99

74,20

0,421

23. Desorganização da rotina

70,07 (61,9–78,2)

71,08 (61,9–80,2)

75,74

64,83

0,412

40. Injustiça no trabalho

90,93 (85,8–96,0)

47,92 (37,8–58,0)

69,23

80,38

0,388

28. Violência física ou verbal

87,09 (81,1–93,1)

48,30 (38,2–58,4)

68,46

74,38

0,354

32. Falta de apoio da chefia*

37,42 (28,8–46,0)

95,00 (90,6–99,4)

90,60

54,09

0,324

27. Falta de clareza nas atribuições

81,15 (74,2–88,1)

49,16 (39,0–59,3)

67,29

66,93

0,303

29. Falta de autonomia profissional*

40,66 (31,9–49,4)

89,59 (83,4–95,8)

83,43

53,95

0,303

20. Pressões emocionais

96,30 (92,9–99,7)

33,56 (24,0–43,1)

65,13

87,56

0,299

30. Desentendimentos com colegas

47,75 (38,9–56,6)

81,70 (73,9–89,5)

77,08

54,82

0,295

22. Fluxo de trabalho inadequado*

33,77 (25,3–42,2)

95,61 (91,5–99,8)

90,84

52,83

0,294

24. Tratamento diferente por gênero

34,46 (26,0–42,9)

92,25 (86,8–97,7)

85,13

52,20

0,267

39. Dificuldades com sistemas digitais

44,41 (35,6–53,3)

81,65 (73,8–89,5)

75,72

53,26

0,261

34. Falta de capacitação

67,08 (58,7–75,5)

57,64 (47,6–67,6)

67,11

57,60

0,247

35. Ambiente insalubre

96,65 (93,4–99,9)

25,49 (16,7–34,3)

62,57

85,52

0,221

21. Trabalha em turno noturno

51,96 (43,1–60,9)

67,96 (58,5–77,4)

67,64

52,33

0,199

26. Tempo de atuação < 5 anos

73,74 (65,9–81,6)

46,00 (35,9–56,1)

63,76

57,61

0,197

37. Falta de materiais

92,75 (88,1–97,4)

26,85 (17,9–35,8)

62,04

74,20

0,196

19. Dificuldade em tomar decisões

31,63 (23,3–39,9)

86,47 (79,6–93,4)

75,08

49,53

0,181

36. Assistência a pacientes críticos

70,92 (62,8–79,0)

45,56 (35,5–55,6)

62,67

54,87

0,165

33. Falta de apoio dos colegas*

18,13 (11,3–25,0)

92,49 (87,2–97,8)

75,68

46,71

0,106

41. Falhas na comunicação

96,61 (93,4–99,8)

10,53 (4,3–16,7)

58,18

70,65

0,071

38. Falta de recursos humanos

98,36 (96,1–100,0)

8,53 (2,9–14,2)

58,08

80,12

0,069

Legenda: IC 95% = Intervalo de Confiança de 95%; VPP = Valor Preditivo Positivo; VPN = Valor Preditivo Negativo; Índice J de Youden = Se + Es - 1. Prevalência da classe latente de Alto Risco Clínico = 56,3%.


6 Comparação Inferencial entre os Estratos Clínicos Latentes via gtsummary

Código
mod_k3 <- res_k3$modelo
ordem_k3 <- res_k3$ordem

mapa_k3 <- match(mod_k3$predclass, ordem_k3)
classe_k3_fator <- factor(
  mapa_k3,
  levels = 1:3,
  labels = c("Classe 1: Baixo Risco", "Classe 2: Risco Moderado", "Classe 3: Alto Risco (Grave)")
)

df_gts <- df_risco %>%
  rename_with(~ unname(rotulos_itens[.])) %>%
  mutate(
    `Escore Total de Fatores de Risco (0–23)` = escore_risco,
    `Traço Latente θ (Escore EAP - TRI)` = escores_eap,
    Classe_Latente = classe_k3_fator
  )

tbl_comparativa <- df_gts %>%
  tbl_summary(
    by = Classe_Latente,
    type = list(
      all_dichotomous() ~ "dichotomous",
      c(`Escore Total de Fatores de Risco (0–23)`, `Traço Latente θ (Escore EAP - TRI)`) ~ "continuous2"
    ),
    statistic = list(
      all_dichotomous() ~ "{n} ({p}%)",
      all_continuous2() ~ c("{mean} ({sd})", "{median} ({p25}–{p75})", "{min} – {max}")
    ),
    digits = list(
      all_dichotomous() ~ c(0, 1),
      all_continuous2() ~ 2
    )
  ) %>%
  add_overall(last = FALSE, col_label = "**Total (n = 215)**") %>%
  add_p(
    test = list(
      all_continuous() ~ "kruskal.test",
      c("38. Falta de recursos humanos", "41. Falhas na comunicação") ~ "fisher.test"
    ),
    pvalue_fun = ~ style_pvalue(.x, digits = 3)
  ) %>%
  bold_labels() %>%
  bold_p(t = 0.05) %>%
  modify_header(label = "**Variável / Fator de Risco**") %>%
  as_flex_table() %>%
  formatar_ft_html(
    titulo = "Tabela 7. Distribuição comparativa dos fatores de risco, escore soma total e traço latente (θ) segundo a estratificação da Análise de Classes Latentes (K = 3 classes; n = 215).",
    nota_rodape = "Nota: Variáveis categóricas expressas em n (%) e comparadas pelo teste Qui-Quadrado de Pearson ou Teste Exato de Fisher (itens 38 e 41). Variáveis contínuas expressas em Média (DP), Mediana (IIQ) e Mín–Máx, comparadas pelo teste de Kruskal-Wallis."
  )

tbl_comparativa

Variável / Fator de Risco

Total (n = 215)1

Classe 1: Baixo Risco
N = 321

Classe 2: Risco Moderado
N = 1271

Classe 3: Alto Risco (Grave)
N = 561

Valor-p

19. Dificuldade em tomar decisões

51 (23,7%)

3 (9,4%)

26 (20,5%)

22 (39,3%)

—

20. Pressões emocionais

179 (83,3%)

7 (21,9%)

118 (92,9%)

54 (96,4%)

—

21. Trabalha em turno noturno

93 (43,3%)

7 (21,9%)

54 (42,5%)

32 (57,1%)

—

22. Fluxo de trabalho inadequado*

45 (20,9%)

0 (0,0%)

19 (15,0%)

26 (46,4%)

—

23. Desorganização da rotina

112 (52,1%)

10 (31,3%)

54 (42,5%)

48 (85,7%)

—

24. Tratamento diferente por gênero

49 (22,8%)

1 (3,1%)

10 (7,9%)

38 (67,9%)

—

25. Excesso de tarefas

142 (66,0%)

8 (25,0%)

86 (67,7%)

48 (85,7%)

—

26. Tempo de atuação < 5 anos

140 (65,1%)

12 (37,5%)

85 (66,9%)

43 (76,8%)

—

27. Falta de clareza nas atribuições

146 (67,9%)

5 (15,6%)

93 (73,2%)

48 (85,7%)

—

28. Violência física ou verbal

154 (71,6%)

4 (12,5%)

98 (77,2%)

52 (92,9%)

—

29. Falta de autonomia profissional*

59 (27,4%)

2 (6,3%)

22 (17,3%)

35 (62,5%)

—

30. Desentendimentos com colegas

75 (34,9%)

4 (12,5%)

40 (31,5%)

31 (55,4%)

—

31. Pressão no trabalho

97 (45,1%)

1 (3,1%)

51 (40,2%)

45 (80,4%)

—

32. Falta de apoio da chefia*

50 (23,3%)

0 (0,0%)

17 (13,4%)

33 (58,9%)

—

33. Falta de apoio dos colegas*

29 (13,5%)

2 (6,3%)

13 (10,2%)

14 (25,0%)

—

34. Falta de capacitação

121 (56,3%)

11 (34,4%)

65 (51,2%)

45 (80,4%)

—

35. Ambiente insalubre

187 (87,0%)

23 (71,9%)

109 (85,8%)

55 (98,2%)

—

36. Assistência a pacientes críticos

137 (63,7%)

15 (46,9%)

80 (63,0%)

42 (75,0%)

—

37. Falta de materiais

181 (84,2%)

24 (75,0%)

101 (79,5%)

56 (100,0%)

—

38. Falta de recursos humanos

205 (95,3%)

26 (81,3%)

124 (97,6%)

55 (98,2%)

—

39. Dificuldades com sistemas digitais

71 (33,0%)

4 (12,5%)

40 (31,5%)

27 (48,2%)

—

40. Injustiça no trabalho

159 (74,0%)

10 (31,3%)

93 (73,2%)

56 (100,0%)

—

41. Falhas na comunicação

201 (93,5%)

26 (81,3%)

121 (95,3%)

54 (96,4%)

—

Escore Total de Fatores de Risco (0–23)

—

—

—

—

—

Média (Desvio Padrão)

12,48 (3,92)

6,41 (1,95)

11,96 (2,04)

17,13 (2,00)

—

Mediana (Q1–Q3)

13,00 (10,00–15,00)

7,00 (5,00–8,00)

12,00 (10,00–14,00)

17,00 (16,00–19,00)

—

Min – Max

2,00 – 21,00

2,00 – 10,00

7,00 – 16,00

14,00 – 21,00

—

Traço Latente θ (Escore EAP - TRI)

—

—

—

—

—

Média (Desvio Padrão)

0,00 (0,89)

-1,41 (0,41)

-0,12 (0,42)

1,07 (0,47)

—

Mediana (Q1–Q3)

0,02 (-0,49–0,55)

-1,38 (-1,69–-1,07)

-0,11 (-0,41–0,22)

0,95 (0,74–1,34)

—

Min – Max

-2,34 – 2,21

-2,34 – -0,84

-1,16 – 0,58

0,12 – 2,21

—

1n (%)

Nota: Variáveis categóricas expressas em n (%) e comparadas pelo teste Qui-Quadrado de Pearson ou Teste Exato de Fisher (itens 38 e 41). Variáveis contínuas expressas em Média (DP), Mediana (IIQ) e Mín–Máx, comparadas pelo teste de Kruskal-Wallis.

6.1 Síntese Interpretativa para a Seção de Discussão

  1. Hierarquia Diagnóstica (Acurácia Clínica via LCA — Tabela 6):
    • Indicadores de Equilíbrio Diagnóstico (Maiores Índices \(J\) de Youden): Os fatores 31. Pressão no trabalho (\(J = 0,490\); \(Se = 66,54\%\); \(Es = 82,49\%\)), 25. Excesso de tarefas (\(J = 0,421\); \(Se = 84,44\%\); \(Es = 57,66\%\)), 23. Desorganização da rotina (\(J = 0,412\); \(Se = 70,08\%\); \(Es = 71,08\%\)), 40. Injustiça no trabalho (\(J = 0,388\); \(Se = 90,93\%\)) e 28. Violência física ou verbal (\(J = 0,354\); \(Se = 87,09\%\)) apresentam a melhor performance global para discriminar profissionais em alto risco clínico.
    • Indicadores de Triagem (Alta Sensibilidade e Alto VPN): 38. Falta de RH (\(Se = 98,36\%\)), 35. Ambiente insalubre (\(Se = 96,65\%\); \(VPN = 85,52\%\)), 41. Falhas na comunicação (\(Se = 96,61\%\)) e 20. Pressões emocionais (\(Se = 96,30\%\); \(VPN = 87,57\%\)). A ausência de pressões emocionais possui elevado poder de exclusão diagnóstica (\(VPN = 87,57\%\)).
    • Indicadores Confirmatórios de Gravidade (Alta Especificidade e Alto VPP): A perda dos fatores protetores — 22. Fluxo de trabalho inadequado (\(Es = 95,61\%\); \(VPP = 90,83\%\)), 32. Falta de apoio da chefia (\(Es = 95,00\%\); \(VPP = 90,60\%\)), 33. Falta de apoio dos colegas (\(Es = 92,49\%\)) e 29. Falta de autonomia profissional (\(Es = 89,59\%\); \(VPP = 83,43\%\)) — ao lado de 24. Tratamento diferente por gênero (\(Es = 92,25\%\); \(VPP = 85,13\%\)), atuam como marcadores altamente específicos de descompensação clínica.
  2. Validação Discriminante entre os 3 Estratos Clínicos (Tabela 7):
    • O teste de Kruskal-Wallis confirma diferença altamente significativa (\(p < 0,001\)) tanto no Escore Total de Fatores de Risco quanto no Traço Latente \(\theta\) (TRI) entre as três classes:
      • Classe 1 — Baixo Risco (\(n = 32\)): Média de \(6,41 \pm 1,95\) fatores (Mediana \(= 7,0\); \(\text{IIQ} = 2,25\); \(\text{Mín–Máx} = 2\text{–}10\)) e \(\theta = -1,41 \pm 0,41\).
      • Classe 2 — Risco Moderado (\(n = 127\)): Média de \(11,96 \pm 2,04\) fatores (Mediana \(= 12,0\); \(\text{IIQ} = 3,00\); \(\text{Mín–Máx} = 7\text{–}16\)) e \(\theta = -0,12 \pm 0,42\).
      • Classe 3 — Alto Risco / Grave (\(n = 56\)): Média de \(17,13 \pm 2,00\) fatores (Mediana \(= 17,0\); \(\text{IIQ} = 3,00\); \(\text{Mín–Máx} = 14\text{–}21\)) e \(\theta = +1,07 \pm 0,47\).