# =============================================================================
# Nama : Syamsiatul Ramadhani
# NIM : 2611018014
# DOSEN : DR.M.FATHURAHMAN,S.SI,M.Si
# =============================================================================

#  REPEATED MEASURE ANALYSIS DENGAN R
#  Contoh terapan: Program manajemen stres dan skor Perceived Stress Scale (PSS-10)
#  pada mahasiswa (DATA SIMULASI)
#
#  Isi:
#   0. Paket & pengaturan
#   1. Simulasi data (format panjang & lebar)
#   2. Eksplorasi data: statistik deskriptif, profile plot, spaghetti plot
#   3. Repeated Measure ANOVA satu arah (within-subject: Waktu)
#        3a. Uji asumsi: outlier, normalitas, sfierisitas (Mauchly)
#        3b. ANOVA + koreksi Greenhouse-Geisser / Huynh-Feldt
#        3c. Pendekatan multivariat (MANOVA) sebagai pembanding
#        3d. Post hoc berpasangan & kontras polinomial (tren)
#        3e. Alternatif nonparametrik: uji Friedman
#   4. Mixed Design ANOVA (between: Kelompok x within: Waktu)
#        4a. Uji asumsi: outlier, normalitas, Levene, Box's M, Mauchly
#        4b. ANOVA campuran + ukuran efek
#        4c. Analisis efek sederhana (simple effects) & post hoc
#        4d. Kontras interaksi (perubahan dari baseline antarkelompok)
#   5. Pembanding: Linear Mixed Model (LMM)
#   6. Menyimpan data & ringkasan hasil
# =============================================================================
# 0. PAKET & PENGATURAN
# Jalankan sekali bila paket belum terpasang:
# install.packages(c("tidyverse", "afex", "emmeans", "rstatix", "car",
#                    "effectsize", "lme4", "lmerTest", "performance", "ggpubr"))

suppressPackageStartupMessages({
  library(dplyr)       # manipulasi data
  library(tidyr)       # format panjang <-> lebar
  library(ggplot2)     # grafik
  library(afex)        # ANOVA within/mixed (tipe III, koreksi GG/HF, MANOVA)
  library(emmeans)     # rerata marginal, efek sederhana, post hoc, kontras
  library(rstatix)     # uji asumsi yang ramah pipe (outlier, Shapiro, Levene, Box's M)
  library(car)         # leveneTest, Anova
  library(effectsize)  # eta kuadrat parsial, omega kuadrat
  library(lme4)        # linear mixed model
  library(lmerTest)    # uji F/t dengan derajat bebas Satterthwaite / Kenward-Roger
})

options(contrasts = c("contr.sum", "contr.poly"))  # kontras jumlah-nol untuk SS tipe III
afex_options(emmeans_model = "multivariate")          # post hoc memakai model multivariat (tahan terhadap non-sfierisitas)
theme_set(theme_bw(base_size = 12))
# 1. SIMULASI DATA
# Skenario: studi intervensi berkelompok pada 90 mahasiswa dengan tingkat stres sedang-tinggi
# diacak ke tiga kelompok (n = 30 per kelompok):
#   - Kontrol       : edukasi kesehatan mental umum
#   - Mindfulness   : latihan mindfulness terstruktur
#   - Mindfulness+AF: latihan mindfulness + aktivitas fisik terstruktur (3x/minggu)
# Skor stres PSS-10 (rentang 0-40; skor lebih tinggi = stres lebih berat) diukur pada minggu ke-0 (baseline), 4, 8, 12.
#
# Struktur korelasi dibangkitkan dari intersep acak + kemiringan acak per subjek,
# sehingga varians meningkat dan korelasi menurun seiring jarak waktu --
# kondisi realistis yang cenderung MELANGGAR asumsi sfierisitas.

set.seed(2026)

n_per   <- 30
kel_lab <- c("Kontrol", "Mindfulness", "Mindfulness+AF")
minggu  <- c(0, 4, 8, 12)

# Rerata populasi skor PSS-10 per kelompok x waktu
mu <- rbind(
  "Kontrol"        = c(26, 25.5, 25, 24.5),
  "Mindfulness"    = c(26, 23, 21, 19.5),
  "Mindfulness+AF" = c(26, 22, 19, 16.5)
)

sd_int   <- 4     # SD intersep acak (perbedaan skor stres dasar antar mahasiswa)
sd_slope <- 0.22  # SD kemiringan acak per minggu (perbedaan respons antar mahasiswa)
sd_eps   <- 2.2   # SD galat pengukuran

dat_wide <- lapply(seq_along(kel_lab), function(g) {
  id    <- (g - 1) * n_per + seq_len(n_per)
  b0    <- rnorm(n_per, 0, sd_int)
  b1    <- rnorm(n_per, 0, sd_slope)
  y     <- sapply(seq_along(minggu), function(t)
    mu[g, t] + b0 + b1 * minggu[t] + rnorm(n_per, 0, sd_eps))
  colnames(y) <- paste0("PSS_M", minggu)
  data.frame(id       = sprintf("P%03d", id),
             kelompok = kel_lab[g],
             usia     = round(runif(n_per, 18, 25)),
             jk       = sample(c("L", "P"), n_per, replace = TRUE, prob = c(.45, .55)),
             round(y, 1))
}) |> bind_rows()

dat_wide$kelompok <- factor(dat_wide$kelompok, levels = kel_lab)
dat_wide$id       <- factor(dat_wide$id)

# Format panjang (satu baris = satu pengukuran), dibutuhkan afex/rstatix/lme4
dat_long <- dat_wide |>
  pivot_longer(starts_with("PSS_M"), names_to = "waktu", values_to = "pss") |>
  mutate(waktu  = factor(waktu, levels = paste0("PSS_M", minggu),
                         labels = paste0("M", minggu)),
         minggu = as.numeric(sub("M", "", waktu)))

head(dat_wide)
##     id kelompok usia jk PSS_M0 PSS_M4 PSS_M8 PSS_M12
## 1 P001  Kontrol   20  L   27.8   22.8   30.3    25.2
## 2 P002  Kontrol   20  L   22.0   24.6   25.7    21.4
## 3 P003  Kontrol   24  P   26.1   24.8   25.6    26.6
## 4 P004  Kontrol   19  P   25.0   27.6   27.2    26.1
## 5 P005  Kontrol   22  P   19.5   19.0   18.8    23.6
## 6 P006  Kontrol   20  L   15.3   15.9   18.0    20.0
head(dat_long)
## # A tibble: 6 × 7
##   id    kelompok  usia jk    waktu   pss minggu
##   <fct> <fct>    <dbl> <chr> <fct> <dbl>  <dbl>
## 1 P001  Kontrol     20 L     M0     27.8      0
## 2 P001  Kontrol     20 L     M4     22.8      4
## 3 P001  Kontrol     20 L     M8     30.3      8
## 4 P001  Kontrol     20 L     M12    25.2     12
## 5 P002  Kontrol     20 L     M0     22        0
## 6 P002  Kontrol     20 L     M4     24.6      4
str(dat_long)
## tibble [360 × 7] (S3: tbl_df/tbl/data.frame)
##  $ id      : Factor w/ 90 levels "P001","P002",..: 1 1 1 1 2 2 2 2 3 3 ...
##  $ kelompok: Factor w/ 3 levels "Kontrol","Mindfulness",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ usia    : num [1:360] 20 20 20 20 20 20 20 20 24 24 ...
##  $ jk      : chr [1:360] "L" "L" "L" "L" ...
##  $ waktu   : Factor w/ 4 levels "M0","M4","M8",..: 1 2 3 4 1 2 3 4 1 2 ...
##  $ pss     : num [1:360] 27.8 22.8 30.3 25.2 22 24.6 25.7 21.4 26.1 24.8 ...
##  $ minggu  : num [1:360] 0 4 8 12 0 4 8 12 0 4 ...
# 2. EKSPLORASI DATA
desk <- dat_long |>
  group_by(kelompok, waktu) |>
  get_summary_stats(pss, type = "mean_sd")
desk
## # A tibble: 12 × 6
##    kelompok       waktu variable     n  mean    sd
##    <fct>          <fct> <fct>    <dbl> <dbl> <dbl>
##  1 Kontrol        M0    pss         30  25.8  5.41
##  2 Kontrol        M4    pss         30  24.6  4.89
##  3 Kontrol        M8    pss         30  25.1  4.28
##  4 Kontrol        M12   pss         30  23.9  4.87
##  5 Mindfulness    M0    pss         30  26.6  4.24
##  6 Mindfulness    M4    pss         30  23.6  4.77
##  7 Mindfulness    M8    pss         30  21.5  4.37
##  8 Mindfulness    M12   pss         30  20.0  4.52
##  9 Mindfulness+AF M0    pss         30  26.3  5.31
## 10 Mindfulness+AF M4    pss         30  22.4  5.41
## 11 Mindfulness+AF M8    pss         30  19.6  5.85
## 12 Mindfulness+AF M12   pss         30  17.7  6.71
# Matriks kovarians & korelasi antarwaktu (seluruh subjek, dalam kelompok)
# -> memberi gambaran awal apakah sfierisitas masuk akal
S  <- cov(dat_wide[, paste0("PSS_M", minggu)])
R  <- cor(dat_wide[, paste0("PSS_M", minggu)])
round(S, 1); round(R, 2)
##         PSS_M0 PSS_M4 PSS_M8 PSS_M12
## PSS_M0    24.7   18.7   16.9    16.5
## PSS_M4    18.7   25.6   21.2    22.2
## PSS_M8    16.9   21.2   28.6    27.0
## PSS_M12   16.5   22.2   27.0    35.7
##         PSS_M0 PSS_M4 PSS_M8 PSS_M12
## PSS_M0    1.00   0.74   0.64    0.56
## PSS_M4    0.74   1.00   0.78    0.73
## PSS_M8    0.64   0.78   1.00    0.85
## PSS_M12   0.56   0.73   0.85    1.00
# Varians selisih antarpasangan waktu (inti asumsi sfierisitas)
pasangan <- combn(paste0("PSS_M", minggu), 2)
var_selisih <- apply(pasangan, 2, function(p) var(dat_wide[[p[1]]] - dat_wide[[p[2]]]))
names(var_selisih) <- apply(pasangan, 2, paste, collapse = " - ")
round(var_selisih, 1)
##  PSS_M0 - PSS_M4  PSS_M0 - PSS_M8 PSS_M0 - PSS_M12  PSS_M4 - PSS_M8 
##             12.9             19.4             27.3             11.7 
## PSS_M4 - PSS_M12 PSS_M8 - PSS_M12 
##             16.9             10.3
# Profile plot: rerata +/- 95% CI per kelompok
p_profil <- ggplot(dat_long, aes(minggu, pss, colour = kelompok, group = kelompok)) +
  stat_summary(fun = mean, geom = "line", linewidth = 1) +
  stat_summary(fun = mean, geom = "point", size = 2.5) +
  stat_summary(fun.data = mean_cl_normal, geom = "errorbar", width = .6) +
  scale_x_continuous(breaks = minggu) +
  labs(x = "Minggu ke-", y = "Skor stres PSS-10", colour = "Kelompok",
       title = "Profil rerata skor stres PSS-10 (± 95% CI)") +
  theme(legend.position = "bottom")
p_profil
## Warning: Computation failed in `stat_summary()`.
## Caused by error in `fun.data()`:
## ! The package "Hmisc" is required.

# Spaghetti plot: lintasan tiap pasien
p_spag <- ggplot(dat_long, aes(minggu, pss, group = id)) +
  geom_line(alpha = .3) +
  stat_summary(aes(group = kelompok), fun = mean, geom = "line",
               colour = "firebrick", linewidth = 1.2) +
  facet_wrap(~ kelompok) +
  scale_x_continuous(breaks = minggu) +
  labs(x = "Minggu ke-", y = "Skor PSS-10", title = "Lintasan individu dan rerata kelompok")
p_spag

# 3. REPEATED MEASURE ANOVA SATU ARAH
#    Pertanyaan: apakah skor stres berubah selama 12 minggu pada kelompok Mindfulness+AF?
d1  <- droplevels(filter(dat_long, kelompok == "Mindfulness+AF"))
d1w <- filter(dat_wide, kelompok == "Mindfulness+AF")

## 3a. Uji asumsi -------------------------------------------------------------
# (i) Outlier per waktu (ekstrem = di luar Q1-3IQR / Q3+3IQR)
d1 |> group_by(waktu) |> identify_outliers(pss)
## [1] waktu      id         kelompok   usia       jk         pss        minggu    
## [8] is.outlier is.extreme
## <0 rows> (or 0-length row.names)
# (ii) Normalitas per waktu (Shapiro-Wilk) dan Q-Q plot
d1 |> group_by(waktu) |> shapiro_test(pss)
## # A tibble: 4 × 4
##   waktu variable statistic     p
##   <fct> <chr>        <dbl> <dbl>
## 1 M0    pss          0.958 0.279
## 2 M4    pss          0.950 0.171
## 3 M8    pss          0.985 0.930
## 4 M12   pss          0.964 0.398
ggpubr::ggqqplot(d1, "pss", facet.by = "waktu")

# (iii) Sfierisitas: Mauchly (dilaporkan otomatis oleh anova_test & afex)
aov1_rs <- anova_test(data = d1, dv = pss, wid = id, within = waktu,
                      effect.size = "pes")
aov1_rs                    # berisi: ANOVA, Mauchly's Test, koreksi GG & HF
## ANOVA Table (type III tests)
## 
## $ANOVA
##   Effect DFn DFd      F        p p<.05   pes
## 1  waktu   3  87 51.441 3.22e-19     * 0.639
## 
## $`Mauchly's Test for Sphericity`
##   Effect     W     p p<.05
## 1  waktu 0.535 0.004     *
## 
## $`Sphericity Corrections`
##   Effect   GGe      DF[GG]    p[GG] p[GG]<.05   HFe     DF[HF]    p[HF]
## 1  waktu 0.708 2.12, 61.62 2.78e-14         * 0.766 2.3, 66.63 2.94e-15
##   p[HF]<.05
## 1         *
get_anova_table(aov1_rs, correction = "auto")  # auto: GG dipakai jika Mauchly p < .05
## ANOVA Table (type III tests)
## 
##   Effect  DFn   DFd      F        p p<.05   pes
## 1  waktu 2.12 61.62 51.441 2.78e-14     * 0.639
## 3b. ANOVA dengan afex (sumber utama laporan) -------------------------------
aov1 <- aov_ez(id = "id", dv = "pss", data = d1, within = "waktu",
               anova_table = list(es = c("ges", "pes"), correction = "GG"))
aov1                       # tabel ringkas (df sudah dikoreksi GG)
## Anova Table (Type 3 tests)
## 
## Response: pss
##   Effect          df   MSE         F  ges  pes p.value
## 1  waktu 2.12, 61.62 11.39 51.44 *** .239 .639   <.001
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1
## 
## Sphericity correction method: GG
summary(aov1)              # univariat tanpa koreksi + Mauchly + epsilon GG & HF
## 
## Univariate Type III Repeated-Measures ANOVA Assuming Sphericity
## 
##             Sum Sq num Df Error SS den Df F value    Pr(>F)    
## (Intercept)  55406      1   3264.4     29 492.204 < 2.2e-16 ***
## waktu         1245      3    701.9     87  51.441 < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## 
## Mauchly Tests for Sphericity
## 
##       Test statistic  p-value
## waktu         0.5354 0.003957
## 
## 
## Greenhouse-Geisser and Huynh-Feldt Corrections
##  for Departure from Sphericity
## 
##        GG eps Pr(>F[GG])    
## waktu 0.70831  2.782e-14 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##          HF eps   Pr(>F[HF])
## waktu 0.7658601 2.942126e-15
# Ukuran efek tambahan
eta_squared(aov1, partial = TRUE)
## # Effect Size for ANOVA (Type III)
## 
## Parameter | Eta2 (partial) |       95% CI
## -----------------------------------------
## waktu     |           0.64 | [0.54, 1.00]
## 
## - One-sided CIs: upper bound fixed at [1.00].
omega_squared(aov1, partial = TRUE)
## # Effect Size for ANOVA (Type III)
## 
## Parameter | Omega2 (partial) |       95% CI
## -------------------------------------------
## waktu     |             0.23 | [0.10, 1.00]
## 
## - One-sided CIs: upper bound fixed at [1.00].
## 3c. Pendekatan multivariat (tidak memerlukan sfierisitas) ------------------
aov1$Anova                 # Pillai, Wilks, Hotelling-Lawley, Roy
## 
## Type III Repeated Measures MANOVA Tests: Pillai test statistic
##             Df test stat approx F num Df den Df    Pr(>F)    
## (Intercept)  1   0.94436   492.20      1     29 < 2.2e-16 ***
## waktu        1   0.76422    29.17      3     27 1.272e-08 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 3d. Post hoc & kontras tren ------------------------------------------------
em1 <- emmeans(aov1, ~ waktu)
em1
##  waktu emmean    SE df lower.CL upper.CL
##  M0      26.3 0.970 29     24.3     28.2
##  M4      22.4 0.987 29     20.4     24.4
##  M8      19.6 1.070 29     17.4     21.8
##  M12     17.7 1.230 29     15.2     20.2
## 
## Confidence level used: 0.95
pairs(em1, adjust = "bonferroni")          # semua pasangan waktu (6 perbandingan)
##  contrast estimate    SE df t.ratio p.value
##  M0 - M4      3.88 0.704 29   5.508 <0.0001
##  M0 - M8      6.64 0.739 29   8.990 <0.0001
##  M0 - M12     8.57 1.000 29   8.571 <0.0001
##  M4 - M8      2.77 0.491 29   5.637 <0.0001
##  M4 - M12     4.69 0.745 29   6.301 <0.0001
##  M8 - M12     1.93 0.625 29   3.084  0.0267
## 
## P value adjustment: bonferroni method for 6 tests
contrast(em1, "trt.vs.ctrl", ref = 1, adjust = "holm")  # tiap waktu vs baseline
##  contrast estimate    SE df t.ratio p.value
##  M4 - M0     -3.88 0.704 29  -5.508 <0.0001
##  M8 - M0     -6.64 0.739 29  -8.990 <0.0001
##  M12 - M0    -8.57 1.000 29  -8.571 <0.0001
## 
## P value adjustment: holm method for 3 tests
contrast(em1, "poly")                      # tren linear, kuadratik, kubik
##  contrast  estimate    SE df t.ratio p.value
##  linear      -28.48 3.140 29  -9.058 <0.0001
##  quadratic     1.95 0.864 29   2.258  0.0317
##  cubic        -0.27 1.590 29  -0.170  0.8662
## 3e. Alternatif nonparametrik ------------------------------------------------
friedman_test(d1, pss ~ waktu | id)
## # A tibble: 1 × 6
##   .y.       n statistic    df        p method       
## * <chr> <int>     <dbl> <dbl>    <dbl> <chr>        
## 1 pss      30      56.6     3 3.07e-12 Friedman test
friedman_effsize(d1, pss ~ waktu | id)     # Kendall's W
## # A tibble: 1 × 5
##   .y.       n effsize method    magnitude
## * <chr> <int>   <dbl> <chr>     <ord>    
## 1 pss      30   0.629 Kendall W large
d1 |> wilcox_test(pss ~ waktu, paired = TRUE, p.adjust.method = "bonferroni")
## # A tibble: 6 × 9
##   .y.   group1 group2    n1    n2 statistic            p      p.adj p.adj.signif
## * <chr> <chr>  <chr>  <int> <int>     <dbl>        <dbl>      <dbl> <chr>       
## 1 pss   M0     M4        30    30      428. 0.0000110       6.57e-5 ****        
## 2 pss   M0     M8        30    30      459  0.0000000261    1.56e-7 ****        
## 3 pss   M0     M12       30    30      458  0.0000000354    2.12e-7 ****        
## 4 pss   M4     M8        30    30      430. 0.00000824      4.94e-5 ****        
## 5 pss   M4     M12       30    30      438  0.00000226      1.35e-5 ****        
## 6 pss   M8     M12       30    30      371  0.00328         1.97e-2 *
# (Opsional) ANOVA robust berbasis trimmed mean -- paket WRS2
if (requireNamespace("WRS2", quietly = TRUE)) {
  print(WRS2::rmanova(d1$pss, d1$waktu, d1$id, tr = 0.2))
}
## Call:
## WRS2::rmanova(y = d1$pss, groups = d1$waktu, blocks = d1$id, 
##     tr = 0.2)
## 
## Test statistic: F = 36.5507 
## Degrees of freedom 1: 2.17 
## Degrees of freedom 2: 36.91 
## p-value: 0
# 4. MIXED DESIGN ANOVA  (Kelompok [between] x Waktu [within])
#    Pertanyaan: apakah pola perubahan skor stres berbeda antarkelompok intervensi?
## 4a. Uji asumsi -------------------------------------------------------------
# (i) Outlier per sel
dat_long |> group_by(kelompok, waktu) |> identify_outliers(pss)
## # A tibble: 3 × 9
##   kelompok waktu id     usia jk      pss minggu is.outlier is.extreme
##   <fct>    <fct> <fct> <dbl> <chr> <dbl>  <dbl> <lgl>      <lgl>     
## 1 Kontrol  M0    P030     22 P      38.2      0 TRUE       FALSE     
## 2 Kontrol  M8    P015     23 P      14.3      8 TRUE       FALSE     
## 3 Kontrol  M12   P015     23 P      11.2     12 TRUE       FALSE
# (ii) Normalitas per sel (3 x 4 = 12 sel) dan residual model
dat_long |> group_by(kelompok, waktu) |> shapiro_test(pss)
## # A tibble: 12 × 5
##    kelompok       waktu variable statistic     p
##    <fct>          <fct> <chr>        <dbl> <dbl>
##  1 Kontrol        M0    pss          0.988 0.977
##  2 Kontrol        M4    pss          0.964 0.381
##  3 Kontrol        M8    pss          0.970 0.552
##  4 Kontrol        M12   pss          0.976 0.715
##  5 Mindfulness    M0    pss          0.959 0.293
##  6 Mindfulness    M4    pss          0.980 0.813
##  7 Mindfulness    M8    pss          0.967 0.455
##  8 Mindfulness    M12   pss          0.972 0.590
##  9 Mindfulness+AF M0    pss          0.958 0.279
## 10 Mindfulness+AF M4    pss          0.950 0.171
## 11 Mindfulness+AF M8    pss          0.985 0.930
## 12 Mindfulness+AF M12   pss          0.964 0.398
ggpubr::ggqqplot(dat_long, "pss", ggtheme = theme_bw()) +
  facet_grid(waktu ~ kelompok)

# (iii) Homogenitas varians antarkelompok pada TIAP waktu (Levene, median-centered)
dat_long |> group_by(waktu) |> levene_test(pss ~ kelompok)
## # A tibble: 4 × 5
##   waktu   df1   df2 statistic       p
##   <fct> <int> <int>     <dbl>   <dbl>
## 1 M0        2    87     0.960 0.387  
## 2 M4        2    87     0.621 0.540  
## 3 M8        2    87     2.20  0.117  
## 4 M12       2    87     5.01  0.00870
# (iv) Homogenitas matriks kovarians antarkelompok (Box's M; uji pada alpha = .001)
box_m(dat_wide[, paste0("PSS_M", minggu)], dat_wide$kelompok)
## # A tibble: 1 × 4
##   statistic p.value parameter method                                            
##       <dbl>   <dbl>     <dbl> <chr>                                             
## 1      19.7   0.480        20 Box's M-test for Homogeneity of Covariance Matric…
# (v) Sfierisitas: Mauchly (dari summary model di bawah)

## 4b. ANOVA campuran ---------------------------------------------------------
aov2 <- aov_ez(id = "id", dv = "pss", data = dat_long,
               between = "kelompok", within = "waktu",
               anova_table = list(es = c("ges", "pes"), correction = "GG"))
aov2
## Anova Table (Type 3 tests)
## 
## Response: pss
##           Effect           df   MSE         F  ges  pes p.value
## 1       kelompok        2, 87 84.24    4.02 * .070 .085    .021
## 2          waktu 2.60, 226.55  7.64 79.76 *** .149 .478   <.001
## 3 kelompok:waktu 5.21, 226.55  7.64 11.62 *** .049 .211   <.001
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1
## 
## Sphericity correction method: GG
summary(aov2)              # Mauchly, epsilon GG/HF, p terkoreksi
## 
## Univariate Type III Repeated-Measures ANOVA Assuming Sphericity
## 
##                Sum Sq num Df Error SS den Df  F value    Pr(>F)    
## (Intercept)    191943      1   7328.8     87 2278.535 < 2.2e-16 ***
## kelompok          677      2   7328.8     87    4.021   0.02137 *  
## waktu            1587      3   1730.8    261   79.755 < 2.2e-16 ***
## kelompok:waktu    462      6   1730.8    261   11.616  1.58e-11 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## 
## Mauchly Tests for Sphericity
## 
##                Test statistic   p-value
## waktu                 0.80905 0.0027491
## kelompok:waktu        0.80905 0.0027491
## 
## 
## Greenhouse-Geisser and Huynh-Feldt Corrections
##  for Departure from Sphericity
## 
##                 GG eps Pr(>F[GG])    
## waktu          0.86799  < 2.2e-16 ***
## kelompok:waktu 0.86799  2.762e-10 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##                   HF eps   Pr(>F[HF])
## waktu          0.8971592 3.753768e-33
## kelompok:waktu 0.8971592 1.466790e-10
aov2$Anova                 # uji multivariat untuk efek within & interaksi
## 
## Type III Repeated Measures MANOVA Tests: Pillai test statistic
##                Df test stat approx F num Df den Df    Pr(>F)    
## (Intercept)     1   0.96322  2278.53      1     87 < 2.2e-16 ***
## kelompok        2   0.08462     4.02      2     87   0.02137 *  
## waktu           1   0.64568    51.63      3     85 < 2.2e-16 ***
## kelompok:waktu  2   0.36988     6.50      6    172 3.336e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Versi rstatix (hasil identik; format ringkas untuk laporan)
aov2_rs <- anova_test(data = dat_long, dv = pss, wid = id,
                      between = kelompok, within = waktu, effect.size = "pes",
                      type = 3)
get_anova_table(aov2_rs, correction = "GG")
## ANOVA Table (type III tests)
## 
##           Effect  DFn    DFd      F        p p<.05   pes
## 1       kelompok 2.00  87.00  4.021 2.10e-02     * 0.085
## 2          waktu 2.60 226.55 79.755 3.68e-32     * 0.478
## 3 kelompok:waktu 5.21 226.55 11.616 2.76e-10     * 0.211
# Ukuran efek
eta_squared(aov2, partial = TRUE)
## # Effect Size for ANOVA (Type III)
## 
## Parameter      | Eta2 (partial) |       95% CI
## ----------------------------------------------
## kelompok       |           0.08 | [0.01, 1.00]
## waktu          |           0.48 | [0.41, 1.00]
## kelompok:waktu |           0.21 | [0.13, 1.00]
## 
## - One-sided CIs: upper bound fixed at [1.00].
omega_squared(aov2, partial = TRUE)
## # Effect Size for ANOVA (Type III)
## 
## Parameter      | Omega2 (partial) |       95% CI
## ------------------------------------------------
## kelompok       |             0.06 | [0.00, 1.00]
## waktu          |             0.15 | [0.08, 1.00]
## kelompok:waktu |             0.04 | [0.00, 1.00]
## 
## - One-sided CIs: upper bound fixed at [1.00].
# Plot interaksi dari model
afex_plot(aov2, x = "waktu", trace = "kelompok", error = "within",
          mapping = c("colour", "shape", "linetype")) +
  labs(y = "Skor PSS-10", x = "Waktu")
## Warning: Panel(s) show a mixed within-between-design.
## Error bars do not allow comparisons across all means.
## Suppress error bars with: error = "none"

## 4c. Efek sederhana (karena interaksi signifikan) ---------------------------
em2 <- emmeans(aov2, ~ waktu | kelompok)

# Efek WAKTU di dalam tiap kelompok (uji F gabungan per kelompok)
joint_tests(aov2, by = "kelompok")
## kelompok = Kontrol:
##  model term df1 df2 F.ratio p.value
##  waktu        3  87   2.434  0.0703
## 
## kelompok = Mindfulness:
##  model term df1 df2 F.ratio p.value
##  waktu        3  87  25.284 <0.0001
## 
## kelompok = Mindfulness+AF:
##  model term df1 df2 F.ratio p.value
##  waktu        3  87  42.023 <0.0001
# Efek KELOMPOK pada tiap waktu
joint_tests(aov2, by = "waktu")
## waktu = M0:
##  model term df1 df2 F.ratio p.value
##  kelompok     2  87   0.223  0.8005
## 
## waktu = M4:
##  model term df1 df2 F.ratio p.value
##  kelompok     2  87   1.444  0.2416
## 
## waktu = M8:
##  model term df1 df2 F.ratio p.value
##  kelompok     2  87   9.792  0.0001
## 
## waktu = M12:
##  model term df1 df2 F.ratio p.value
##  kelompok     2  87   9.874  0.0001
# Post hoc: tiap waktu vs baseline di dalam tiap kelompok
contrast(em2, "trt.vs.ctrl", ref = 1, adjust = "holm")
## kelompok = Kontrol:
##  contrast estimate    SE df t.ratio p.value
##  M4 - M0    -1.197 0.630 87  -1.898  0.1220
##  M8 - M0    -0.677 0.664 87  -1.019  0.3109
##  M12 - M0   -1.893 0.813 87  -2.328  0.0667
## 
## kelompok = Mindfulness:
##  contrast estimate    SE df t.ratio p.value
##  M4 - M0    -2.993 0.630 87  -4.748 <0.0001
##  M8 - M0    -5.187 0.664 87  -7.813 <0.0001
##  M12 - M0   -6.610 0.813 87  -8.126 <0.0001
## 
## kelompok = Mindfulness+AF:
##  contrast estimate    SE df t.ratio p.value
##  M4 - M0    -3.877 0.630 87  -6.149 <0.0001
##  M8 - M0    -6.643 0.664 87 -10.008 <0.0001
##  M12 - M0   -8.570 0.813 87 -10.536 <0.0001
## 
## P value adjustment: holm method for 3 tests
# Post hoc: perbandingan antarkelompok pada tiap waktu
em2b <- emmeans(aov2, ~ kelompok | waktu)
pairs(em2b, adjust = "tukey")             # Tukey per waktu
## waktu = M0:
##  contrast                       estimate   SE df t.ratio p.value
##  Kontrol - Mindfulness            -0.863 1.30 87  -0.667  0.7835
##  Kontrol - (Mindfulness+AF)       -0.480 1.30 87  -0.371  0.9272
##  Mindfulness - (Mindfulness+AF)    0.383 1.30 87   0.296  0.9529
## 
## waktu = M4:
##  contrast                       estimate   SE df t.ratio p.value
##  Kontrol - Mindfulness             0.933 1.30 87   0.718  0.7534
##  Kontrol - (Mindfulness+AF)        2.200 1.30 87   1.693  0.2137
##  Mindfulness - (Mindfulness+AF)    1.267 1.30 87   0.975  0.5947
## 
## waktu = M8:
##  contrast                       estimate   SE df t.ratio p.value
##  Kontrol - Mindfulness             3.647 1.26 87   2.889  0.0134
##  Kontrol - (Mindfulness+AF)        5.487 1.26 87   4.347  0.0001
##  Mindfulness - (Mindfulness+AF)    1.840 1.26 87   1.458  0.3162
## 
## waktu = M12:
##  contrast                       estimate   SE df t.ratio p.value
##  Kontrol - Mindfulness             3.853 1.41 87   2.736  0.0204
##  Kontrol - (Mindfulness+AF)        6.197 1.41 87   4.400 <0.0001
##  Mindfulness - (Mindfulness+AF)    2.343 1.41 87   1.664  0.2249
## 
## P value adjustment: tukey method for comparing a family of 3 estimates
## 4d. Kontras interaksi -------------------------------------------------------
# Apakah penurunan (M12 - M0) berbeda antarkelompok? -- inti pertanyaan uji klinis
em_full <- emmeans(aov2, ~ waktu * kelompok)
contrast(em_full, interaction = list(waktu = list("M12-M0" = c(-1, 0, 0, 1)),
                                     kelompok = "pairwise"),
         adjust = "holm")
##  waktu_custom kelompok_pairwise              estimate   SE df t.ratio p.value
##  M12-M0       Kontrol - Mindfulness              4.72 1.15 87   4.100  0.0002
##  M12-M0       Kontrol - (Mindfulness+AF)         6.68 1.15 87   5.804 <0.0001
##  M12-M0       Mindfulness - (Mindfulness+AF)     1.96 1.15 87   1.704  0.0920
## 
## P value adjustment: holm method for 3 tests
# Tren linear per kelompok dan perbandingannya
contrast(em2, "poly")[c(1, 4, 7)]
##  contrast kelompok       estimate   SE df t.ratio p.value
##  linear   Kontrol           -5.16 2.61 87  -1.978  0.0511
##  linear   Mindfulness      -22.02 2.61 87  -8.444 <0.0001
##  linear   Mindfulness+AF   -28.48 2.61 87 -10.918 <0.0001
tren_int <- summary(contrast(em_full, interaction = c(waktu = "poly", kelompok = "pairwise"),
                             adjust = "none"))
tren_lin <- subset(tren_int, waktu_poly == "linear")   # apakah laju penurunan linear berbeda?
tren_lin$p.holm <- p.adjust(tren_lin$p.value, "holm")  # koreksi Holm untuk 3 perbandingan
tren_lin
##   waktu_poly              kelompok_pairwise  estimate       SE df  t.ratio
## 1     linear          Kontrol - Mindfulness 16.863333 3.688574 87 4.571776
## 4     linear     Kontrol - (Mindfulness+AF) 23.316667 3.688574 87 6.321323
## 7     linear Mindfulness - (Mindfulness+AF)  6.453333 3.688574 87 1.749547
##        p.value       p.holm
## 1 1.590100e-05 3.180201e-05
## 4 1.075498e-08 3.226493e-08
## 7 8.372277e-02 8.372277e-02
# 5. PEMBANDING: LINEAR MIXED MODEL (LMM)
#    Tidak mensyaratkan sfierisitas, menampung data hilang (MAR) dan waktu
#    pengukuran yang tidak seragam.
lmm1 <- lmer(pss ~ kelompok * waktu + (1 | id), data = dat_long, REML = TRUE)
lmm2 <- lmer(pss ~ kelompok * waktu + (1 + minggu | id), data = dat_long, REML = TRUE)
anova(lmm1, lmm2, refit = FALSE)          # uji rasio kemungkinan struktur acak
## Data: dat_long
## Models:
## lmm1: pss ~ kelompok * waktu + (1 | id)
## lmm2: pss ~ kelompok * waktu + (1 + minggu | id)
##      npar  AIC    BIC  logLik -2*log(L)  Chisq Df Pr(>Chisq)    
## lmm1   14 1953 2007.4 -962.50      1925                         
## lmm2   16 1939 2001.2 -953.49      1907 18.012  2  0.0001226 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
anova(lmm2, ddf = "Kenward-Roger")        # uji F tipe III efek tetap
## Type III Analysis of Variance Table with Kenward-Roger's method
##                Sum Sq Mean Sq NumDF  DenDF F value    Pr(>F)    
## kelompok        38.96  19.482     2  87.00  4.0210   0.02137 *  
## waktu          773.13 257.711     3 185.37 52.9470 < 2.2e-16 ***
## kelompok:waktu 233.80  38.967     6 206.40  7.9968 9.075e-08 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
performance::icc(lmm1)                    # korelasi intrakelas
## # Intraclass Correlation Coefficient
## 
##     Adjusted ICC: 0.745
##   Unadjusted ICC: 0.577
# Diagnostik residual LMM (normalitas & homogenitas)
par(mfrow = c(1, 3))
qqnorm(resid(lmm2), main = "Q-Q residual"); qqline(resid(lmm2))
qqnorm(ranef(lmm2)$id[, 1], main = "Q-Q intersep acak"); qqline(ranef(lmm2)$id[, 1])
plot(fitted(lmm2), resid(lmm2), xlab = "Nilai prediksi", ylab = "Residual",
     main = "Residual vs prediksi"); abline(h = 0, lty = 2)

par(mfrow = c(1, 1))
# (paket 'see' + performance::check_model(lmm2) memberi panel diagnostik lengkap)

# Simulasi 30 nilai hilang (MCAR, +/- 11% pengukuran pasca-baseline)
# untuk menunjukkan keunggulan LMM
set.seed(1)
dat_miss <- dat_long
dat_miss$pss[sample(which(dat_miss$waktu != "M0"), 30)] <- NA
lmm_miss <- lmer(pss ~ kelompok * waktu + (1 + minggu | id), data = dat_miss,
                 control = lmerControl(optimizer = "bobyqa"))
anova(lmm_miss, ddf = "Kenward-Roger")    # semua pasien tetap dianalisis
## Type III Analysis of Variance Table with Kenward-Roger's method
##                Sum Sq Mean Sq NumDF   DenDF F value    Pr(>F)    
## kelompok        37.92  18.960     2  86.976  3.8056   0.02604 *  
## waktu          765.78 255.259     3 168.318 50.9923 < 2.2e-16 ***
## kelompok:waktu 249.07  41.512     6 185.986  8.2831  5.86e-08 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# RM ANOVA akan membuang seluruh pasien yang punya >= 1 nilai hilang:
n_distinct(dat_miss$id[is.na(dat_miss$pss)])
## [1] 25
library(writexl)
write_xlsx(dat_long, "dat_long.xlsx")
write_xlsx(dat_wide, "dat_wide.xlsx")
getwd()
## [1] "D:/1. KULIAH/1. BIOSTAT/TUGAS 2"