# ============================================================
# TUGAS BIOSTATISTIKA INTERMEDIATE
# Nama : Zulkaeni Septia Rini
# Nim  : 2611018051
# FINAL - REPEATED MEASURES ANALYSIS DENGAN R
# Data simulasi berdasarkan Chikama et al. (2026)
# Outcome: Athens Insomnia Scale (AIS)
# Desain utama: 3 treatment x 3 kali pengukuran
# ============================================================

# Jika paket belum tersedia, jalankan satu kali:
# install.packages(c("dplyr","tidyr","ggplot2","afex","emmeans",
#                    "rstatix","car","effectsize","lme4","lmerTest",
#                    "performance","ggpubr"))

required_packages <- c(
  "dplyr","tidyr","ggplot2","afex","emmeans","rstatix","car",
  "effectsize","lme4","lmerTest","performance","ggpubr"
)
missing_packages <- required_packages[!vapply(required_packages, requireNamespace,
                                               quietly = TRUE, FUN.VALUE = logical(1))]
## Registered S3 method overwritten by 'lme4':
##   method           from
##   na.action.merMod car
if (length(missing_packages) > 0) {
  stop(
    "Paket berikut belum terpasang: ", paste(missing_packages, collapse = ", "),
    "\nJalankan install.packages() seperti pada bagian atas script, lalu ulangi analisis."
  )
}

suppressPackageStartupMessages({
  library(dplyr)
  library(tidyr)
  library(ggplot2)
  library(afex)
  library(emmeans)
  library(rstatix)
  library(car)
  library(effectsize)
  library(lme4)
  library(lmerTest)
  library(performance)
  library(ggpubr)
})

options(contrasts = c("contr.sum", "contr.poly"))
afex_options(emmeans_model = "multivariate")
theme_set(theme_bw(base_size = 12))
# 1. DATA DAN VALIDASI STRUKTUR
data_file <- "FINAL_SLEEP_AIS_Data.csv"
if (!file.exists(data_file)) {
  stop(
    "File data tidak ditemukan: ", data_file,
    "\nPastikan file .R dan FINAL_SLEEP_AIS_Data.csv berada pada folder kerja yang sama."
  )
}

dat_wide <- read.csv(data_file, stringsAsFactors = FALSE)

required_columns <- c("id", "treatment", "AIS_baseline", "AIS_3m", "AIS_6m")
if (!all(required_columns %in% names(dat_wide))) {
  stop("Kolom data tidak lengkap. Kolom wajib: ", paste(required_columns, collapse = ", "))
}
if (anyNA(dat_wide[, required_columns])) {
  stop("Terdapat missing value pada variabel utama. Periksa dataset sebelum analisis.")
}
if (anyDuplicated(dat_wide$id) > 0) {
  stop("ID peserta tidak unik pada data format wide.")
}

# Urutan kelompok dibuat konsisten dengan laporan: A, B, C.
dat_wide$treatment <- factor(
  dat_wide$treatment,
  levels = c(
    "A - Guidance 6 months",
    "B - Guidance 3 months",
    "C - Report only"
  )
)
dat_wide$id <- factor(dat_wide$id)

if (nlevels(dat_wide$treatment) < 3) {
  stop("Desain belum memenuhi minimal 3 treatment.")
}

dat_long <- dat_wide |>
  pivot_longer(
    cols = c(AIS_baseline, AIS_3m, AIS_6m),
    names_to = "time",
    values_to = "AIS"
  ) |>
  mutate(
    time = factor(
      time,
      levels = c("AIS_baseline", "AIS_3m", "AIS_6m"),
      labels = c("Baseline", "3 months", "6 months")
    )
  )

if (nlevels(dat_long$time) < 3) {
  stop("Desain belum memenuhi minimal 3 kali pengukuran.")
}

cat("\n=== VALIDASI DESAIN ===\n")
## 
## === VALIDASI DESAIN ===
cat("Jumlah peserta :", n_distinct(dat_wide$id), "\n")
## Jumlah peserta : 90
cat("Jumlah treatment:", nlevels(dat_wide$treatment), "\n")
## Jumlah treatment: 3
cat("Jumlah waktu    :", nlevels(dat_long$time), "\n")
## Jumlah waktu    : 3
print(table(dat_wide$treatment))
## 
## A - Guidance 6 months B - Guidance 3 months       C - Report only 
##                    30                    30                    30
# 2. EKSPLORASI DATA
cat("\n=== STATISTIK DESKRIPTIF ===\n")
## 
## === STATISTIK DESKRIPTIF ===
descriptive <- dat_long |>
  group_by(treatment, time) |>
  get_summary_stats(AIS, type = "mean_sd")
print(descriptive)
## # A tibble: 9 × 6
##   treatment             time     variable     n  mean    sd
##   <fct>                 <fct>    <fct>    <dbl> <dbl> <dbl>
## 1 A - Guidance 6 months Baseline AIS         30  6.67  2.25
## 2 A - Guidance 6 months 3 months AIS         30  4.93  2.21
## 3 A - Guidance 6 months 6 months AIS         30  5.13  2.28
## 4 B - Guidance 3 months Baseline AIS         30  6.27  2.02
## 5 B - Guidance 3 months 3 months AIS         30  4     2.32
## 6 B - Guidance 3 months 6 months AIS         30  4.87  2.14
## 7 C - Report only       Baseline AIS         30  6.23  2.05
## 8 C - Report only       3 months AIS         30  5.93  2.16
## 9 C - Report only       6 months AIS         30  6.2   2.31
p_profile <- ggplot(dat_long, aes(x = time, y = AIS, colour = treatment,
                                  group = treatment)) +
  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 = 0.08) +
  labs(
    title = "Mean AIS profile (95% CI)",
    x = "Time",
    y = "Athens Insomnia Scale (AIS)",
    colour = "Treatment"
  )
print(p_profile)
## Warning: Computation failed in `stat_summary()`.
## Caused by error in `fun.data()`:
## ! The package "Hmisc" is required.

# 3. ANALISIS TAMBAHAN: REPEATED-MEASURES ANOVA PADA GROUP A
#    Bagian ini bukan analisis utama desain 3 x 3.
cat("\n=== ANALISIS TAMBAHAN: GROUP A ===\n")
## 
## === ANALISIS TAMBAHAN: GROUP A ===
d1 <- droplevels(filter(dat_long, treatment == "A - Guidance 6 months"))

cat("\nNormalitas per waktu - Group A:\n")
## 
## Normalitas per waktu - Group A:
print(d1 |> group_by(time) |> shapiro_test(AIS))
## # A tibble: 3 × 4
##   time     variable statistic      p
##   <fct>    <chr>        <dbl>  <dbl>
## 1 Baseline AIS          0.939 0.0847
## 2 3 months AIS          0.960 0.303 
## 3 6 months AIS          0.953 0.209
aov1 <- aov_ez(
  id = "id",
  dv = "AIS",
  data = d1,
  within = "time",
  anova_table = list(es = c("ges", "pes"), correction = "GG")
)
cat("\nRepeated-measures ANOVA - Group A:\n")
## 
## Repeated-measures ANOVA - Group A:
print(aov1)
## Anova Table (Type 3 tests)
## 
## Response: AIS
##   Effect          df  MSE         F  ges  pes p.value
## 1   time 1.84, 53.47 1.38 21.13 *** .109 .422   <.001
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1
## 
## Sphericity correction method: GG
print(summary(aov1))  # termasuk Mauchly/sphericity bila tersedia
## 
## Univariate Type III Repeated-Measures ANOVA Assuming Sphericity
## 
##              Sum Sq num Df Error SS den Df F value    Pr(>F)    
## (Intercept) 2800.04      1   365.96     29 221.888 4.019e-15 ***
## time          53.96      2    74.04     58  21.132 1.277e-07 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## 
## Mauchly Tests for Sphericity
## 
##      Test statistic p-value
## time        0.91519 0.28917
## 
## 
## Greenhouse-Geisser and Huynh-Feldt Corrections
##  for Departure from Sphericity
## 
##       GG eps Pr(>F[GG])    
## time 0.92182  3.458e-07 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##         HF eps   Pr(>F[HF])
## time 0.9815234 1.615764e-07
cat("\nPost hoc waktu - Group A (Holm):\n")
## 
## Post hoc waktu - Group A (Holm):
print(emmeans(aov1, ~ time) |> pairs(adjust = "holm"))
##  contrast              estimate    SE df t.ratio p.value
##  Baseline - X3.months      1.73 0.318 29   5.454 <0.0001
##  Baseline - X6.months      1.53 0.306 29   5.011 <0.0001
##  X3.months - X6.months    -0.20 0.246 29  -0.812  0.4235
## 
## P value adjustment: holm method for 3 tests
cat("\nAlternatif nonparametrik - Friedman:\n")
## 
## Alternatif nonparametrik - Friedman:
print(friedman_test(d1, AIS ~ time | id))
## # A tibble: 1 × 6
##   .y.       n statistic    df         p method       
## * <chr> <int>     <dbl> <dbl>     <dbl> <chr>        
## 1 AIS      30      20.4     2 0.0000377 Friedman test
# 4. ANALISIS UTAMA: MIXED REPEATED-MEASURES ANOVA 3 x 3
#    Between-subject factor : treatment (3 kelompok)
#    Within-subject factor  : time (3 pengukuran)
cat("\n=== ANALISIS UTAMA: MIXED ANOVA 3 x 3 ===\n")
## 
## === ANALISIS UTAMA: MIXED ANOVA 3 x 3 ===
cat("\nNormalitas per treatment x waktu:\n")
## 
## Normalitas per treatment x waktu:
print(dat_long |> group_by(treatment, time) |> shapiro_test(AIS))
## # A tibble: 9 × 5
##   treatment             time     variable statistic      p
##   <fct>                 <fct>    <chr>        <dbl>  <dbl>
## 1 A - Guidance 6 months Baseline AIS          0.939 0.0847
## 2 A - Guidance 6 months 3 months AIS          0.960 0.303 
## 3 A - Guidance 6 months 6 months AIS          0.953 0.209 
## 4 B - Guidance 3 months Baseline AIS          0.957 0.254 
## 5 B - Guidance 3 months 3 months AIS          0.941 0.0996
## 6 B - Guidance 3 months 6 months AIS          0.956 0.249 
## 7 C - Report only       Baseline AIS          0.935 0.0650
## 8 C - Report only       3 months AIS          0.951 0.175 
## 9 C - Report only       6 months AIS          0.978 0.767
cat("\nHomogenitas varians (Levene) pada setiap waktu:\n")
## 
## Homogenitas varians (Levene) pada setiap waktu:
print(dat_long |> group_by(time) |> levene_test(AIS ~ treatment))
## # A tibble: 3 × 5
##   time       df1   df2 statistic     p
##   <fct>    <int> <int>     <dbl> <dbl>
## 1 Baseline     2    87    0.0861 0.918
## 2 3 months     2    87    0.0786 0.925
## 3 6 months     2    87    0.0246 0.976
cat("\nHomogenitas matriks kovarians (Box's M):\n")
## 
## Homogenitas matriks kovarians (Box's M):
print(box_m(
  dat_wide[, c("AIS_baseline", "AIS_3m", "AIS_6m")],
  dat_wide$treatment
))
## # A tibble: 1 × 4
##   statistic p.value parameter method                                            
##       <dbl>   <dbl>     <dbl> <chr>                                             
## 1      7.12   0.850        12 Box's M-test for Homogeneity of Covariance Matric…
aov2 <- aov_ez(
  id = "id",
  dv = "AIS",
  data = dat_long,
  between = "treatment",
  within = "time",
  anova_table = list(es = c("ges", "pes"), correction = "GG")
)

cat("\nMixed repeated-measures ANOVA:\n")
## 
## Mixed repeated-measures ANOVA:
print(aov2)
## Anova Table (Type 3 tests)
## 
## Response: AIS
##           Effect           df   MSE         F  ges  pes p.value
## 1      treatment        2, 87 12.42      2.10 .040 .046    .128
## 2           time 1.94, 168.95  1.06 47.20 *** .071 .352   <.001
## 3 treatment:time 3.88, 168.95  1.06  9.05 *** .029 .172   <.001
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1
## 
## Sphericity correction method: GG
print(summary(aov2))
## 
## Univariate Type III Repeated-Measures ANOVA Assuming Sphericity
## 
##                Sum Sq num Df Error SS den Df  F value    Pr(>F)    
## (Intercept)    8411.3      1   1080.8     87 677.0957 < 2.2e-16 ***
## treatment        52.3      2   1080.8     87   2.1040    0.1281    
## time             96.9      2    178.6    174  47.2003 < 2.2e-16 ***
## treatment:time   37.2      4    178.6    174   9.0533 1.149e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## 
## Mauchly Tests for Sphericity
## 
##                Test statistic p-value
## time                  0.97008 0.27084
## treatment:time        0.97008 0.27084
## 
## 
## Greenhouse-Geisser and Huynh-Feldt Corrections
##  for Departure from Sphericity
## 
##                 GG eps Pr(>F[GG])    
## time           0.97095  < 2.2e-16 ***
## treatment:time 0.97095  1.572e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##                   HF eps   Pr(>F[HF])
## time           0.9927741 5.361951e-17
## treatment:time 0.9927741 1.241850e-06
cat("\nPartial eta-squared:\n")
## 
## Partial eta-squared:
print(eta_squared(aov2, partial = TRUE))
## # Effect Size for ANOVA (Type III)
## 
## Parameter      | Eta2 (partial) |       95% CI
## ----------------------------------------------
## treatment      |           0.05 | [0.00, 1.00]
## time           |           0.35 | [0.26, 1.00]
## treatment:time |           0.17 | [0.08, 1.00]
## 
## - One-sided CIs: upper bound fixed at [1.00].
# Simple effects
cat("\nSimple effect waktu pada setiap treatment:\n")
## 
## Simple effect waktu pada setiap treatment:
print(joint_tests(aov2, by = "treatment"))
## treatment = A - Guidance 6 months:
##  model term df1 df2 F.ratio p.value
##  time         2  87  23.675 <0.0001
## 
## treatment = B - Guidance 3 months:
##  model term df1 df2 F.ratio p.value
##  time         2  87  37.715 <0.0001
## 
## treatment = C - Report only:
##  model term df1 df2 F.ratio p.value
##  time         2  87   0.922  0.4017
cat("\nSimple effect treatment pada setiap waktu:\n")
## 
## Simple effect treatment pada setiap waktu:
print(joint_tests(aov2, by = "time"))
## time = Baseline:
##  model term df1 df2 F.ratio p.value
##  treatment    2  87   0.393  0.6760
## 
## time = X3.months:
##  model term df1 df2 F.ratio p.value
##  treatment    2  87   5.625  0.0050
## 
## time = X6.months:
##  model term df1 df2 F.ratio p.value
##  treatment    2  87   2.955  0.0574
# Post hoc / contrasts
cat("\nPerbandingan waktu di setiap treatment (baseline sebagai referensi; Holm):\n")
## 
## Perbandingan waktu di setiap treatment (baseline sebagai referensi; Holm):
em_time <- emmeans(aov2, ~ time | treatment)
print(contrast(em_time, "trt.vs.ctrl", ref = 1, adjust = "holm"))
## treatment = A - Guidance 6 months:
##  contrast             estimate    SE df t.ratio p.value
##  X3.months - Baseline  -1.7333 0.261 87  -6.637 <0.0001
##  X6.months - Baseline  -1.5333 0.281 87  -5.463 <0.0001
## 
## treatment = B - Guidance 3 months:
##  contrast             estimate    SE df t.ratio p.value
##  X3.months - Baseline  -2.2667 0.261 87  -8.679 <0.0001
##  X6.months - Baseline  -1.4000 0.281 87  -4.988 <0.0001
## 
## treatment = C - Report only:
##  contrast             estimate    SE df t.ratio p.value
##  X3.months - Baseline  -0.3000 0.261 87  -1.149  0.5077
##  X6.months - Baseline  -0.0333 0.281 87  -0.119  0.9057
## 
## P value adjustment: holm method for 2 tests
cat("\nPerbandingan treatment pada setiap waktu (Tukey):\n")
## 
## Perbandingan treatment pada setiap waktu (Tukey):
em_group <- emmeans(aov2, ~ treatment | time)
print(pairs(em_group, adjust = "tukey"))
## time = Baseline:
##  contrast                                          estimate    SE df t.ratio
##  (A - Guidance 6 months) - (B - Guidance 3 months)   0.4000 0.544 87   0.736
##  (A - Guidance 6 months) - (C - Report only)         0.4333 0.544 87   0.797
##  (B - Guidance 3 months) - (C - Report only)         0.0333 0.544 87   0.061
##  p.value
##   0.7431
##   0.7059
##   0.9979
## 
## time = X3.months:
##  contrast                                          estimate    SE df t.ratio
##  (A - Guidance 6 months) - (B - Guidance 3 months)   0.9333 0.577 87   1.619
##  (A - Guidance 6 months) - (C - Report only)        -1.0000 0.577 87  -1.735
##  (B - Guidance 3 months) - (C - Report only)        -1.9333 0.577 87  -3.354
##  p.value
##   0.2431
##   0.1982
##   0.0034
## 
## time = X6.months:
##  contrast                                          estimate    SE df t.ratio
##  (A - Guidance 6 months) - (B - Guidance 3 months)   0.2667 0.580 87   0.459
##  (A - Guidance 6 months) - (C - Report only)        -1.0667 0.580 87  -1.838
##  (B - Guidance 3 months) - (C - Report only)        -1.3333 0.580 87  -2.297
##  p.value
##   0.8903
##   0.1635
##   0.0615
## 
## P value adjustment: tukey method for comparing a family of 3 estimates
# Perubahan baseline -> 3 bulan dan baseline -> 6 bulan dibandingkan antarkelompok
cat("\nKontras difference-in-change antartreatment (Holm):\n")
## 
## Kontras difference-in-change antartreatment (Holm):
em_full <- emmeans(aov2, ~ time * treatment)
change_contrasts <- contrast(
  em_full,
  interaction = list(
    time = list(
      "3m-base" = c(-1, 1, 0),
      "6m-base" = c(-1, 0, 1)
    ),
    treatment = "pairwise"
  ),
  adjust = "holm"
)
print(change_contrasts)
##  time_custom treatment_pairwise                                estimate    SE
##  3m-base     (A - Guidance 6 months) - (B - Guidance 3 months)    0.533 0.369
##  6m-base     (A - Guidance 6 months) - (B - Guidance 3 months)   -0.133 0.397
##  3m-base     (A - Guidance 6 months) - (C - Report only)         -1.433 0.369
##  6m-base     (A - Guidance 6 months) - (C - Report only)         -1.500 0.397
##  3m-base     (B - Guidance 3 months) - (C - Report only)         -1.967 0.369
##  6m-base     (B - Guidance 3 months) - (C - Report only)         -1.367 0.397
##  df t.ratio p.value
##  87   1.444  0.3047
##  87  -0.336  0.7378
##  87  -3.881  0.0010
##  87  -3.779  0.0012
##  87  -5.325 <0.0001
##  87  -3.443  0.0027
## 
## P value adjustment: holm method for 6 tests
# 5. LINEAR MIXED MODEL (PEMBANDING)
cat("\n=== PEMBANDING: LINEAR MIXED MODEL ===\n")
## 
## === PEMBANDING: LINEAR MIXED MODEL ===
lmm <- lmer(AIS ~ treatment * time + (1 | id), data = dat_long, REML = TRUE)
print(anova(lmm, ddf = "Kenward-Roger"))
## Type III Analysis of Variance Table with Kenward-Roger's method
##                Sum Sq Mean Sq NumDF DenDF F value    Pr(>F)    
## treatment       4.319   2.160     2    87  2.1040    0.1281    
## time           96.896  48.448     2   174 47.2003 < 2.2e-16 ***
## treatment:time 37.170   9.293     4   174  9.0533 1.149e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
print(summary(lmm))
## Linear mixed model fit by REML. t-tests use Satterthwaite's method [
## lmerModLmerTest]
## Formula: AIS ~ treatment * time + (1 | id)
##    Data: dat_long
## 
## REML criterion at convergence: 1008.2
## 
## Scaled residuals: 
##      Min       1Q   Median       3Q      Max 
## -2.13333 -0.51716  0.01363  0.51692  2.22260 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  id       (Intercept) 3.799    1.949   
##  Residual             1.026    1.013   
## Number of obs: 270, groups:  id, 90
## 
## Fixed effects:
##                    Estimate Std. Error         df t value Pr(>|t|)    
## (Intercept)        5.581481   0.214499  86.999996  26.021  < 2e-16 ***
## treatment1        -0.003704   0.303347  86.999996  -0.012 0.990286    
## treatment2        -0.537037   0.303347  86.999996  -1.770 0.080168 .  
## time1              0.807407   0.087197 174.000001   9.260  < 2e-16 ***
## time2             -0.625926   0.087197 174.000001  -7.178 1.96e-11 ***
## treatment1:time1   0.281481   0.123315 174.000001   2.283 0.023662 *  
## treatment2:time1   0.414815   0.123315 174.000001   3.364 0.000945 ***
## treatment1:time2  -0.018519   0.123315 174.000001  -0.150 0.880802    
## treatment2:time2  -0.418519   0.123315 174.000001  -3.394 0.000853 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Correlation of Fixed Effects:
##             (Intr) trtmn1 trtmn2 time1  time2  trt1:1 trt2:1 trt1:2
## treatment1   0.000                                                 
## treatment2   0.000 -0.500                                          
## time1        0.000  0.000  0.000                                   
## time2        0.000  0.000  0.000 -0.500                            
## trtmnt1:tm1  0.000  0.000  0.000  0.000  0.000                     
## trtmnt2:tm1  0.000  0.000  0.000  0.000  0.000 -0.500              
## trtmnt1:tm2  0.000  0.000  0.000  0.000  0.000 -0.500  0.250       
## trtmnt2:tm2  0.000  0.000  0.000  0.000  0.000  0.250 -0.500 -0.500
print(performance::icc(lmm))
## # Intraclass Correlation Coefficient
## 
##     Adjusted ICC: 0.787
##   Unadjusted ICC: 0.688
cat("\nAnalisis selesai. Analisis utama tugas adalah Mixed Repeated-Measures ANOVA 3 treatment x 3 pengukuran.\n")
## 
## Analisis selesai. Analisis utama tugas adalah Mixed Repeated-Measures ANOVA 3 treatment x 3 pengukuran.