# =============================================================================
# Nama : [Bayu Rosandy]
# NIM : [2611018001]
# =============================================================================
#
# REPEATED MEASURE ANALYSIS DENGAN R
# Contoh terapan: Program pelatihan keselamatan kerja dan kepatuhan SOP
# pada operator produksi (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
# install.packages(c("tidyverse","afex","emmeans","rstatix","car",
# "effectsize","lme4","lmerTest","performance","ggpubr","Hmisc"))
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. SIMULASI DATA
# Skenario: 90 operator produksi diacak ke tiga kelompok:
# - Kontrol : briefing keselamatan kerja standar
# - Video : pelatihan keselamatan kerja berbasis video
# - Video+Simulasi : video + simulasi praktik prosedur keselamatan
# Skor kepatuhan SOP (0–100) diukur pada minggu 0, 4, 8, 12.
#
# Struktur korelasi dibuat dari intersep acak + kemiringan acak per subjek
# agar data realistis dan cenderung melanggar asumsi sfierisitas.
set.seed(2027)
n_per <- 30
kel_lab <- c("Kontrol","Video","Video+Simulasi")
minggu <- c(0,4,8,12)
mu <- rbind(
"Kontrol" = c(68,68.5,69,69.2),
"Video" = c(68,74,78,80),
"Video+Simulasi" = c(68,76,82,86)
)
sd_int <- 6
sd_slope <- 0.35
sd_eps <- 3.5
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)
pmin(pmax(mu[g,t] + b0 + b1*minggu[t] + rnorm(n_per,0,sd_eps),0),100))
colnames(y) <- paste0("SOP_M",minggu)
data.frame(
id = sprintf("K%02d%02d",g,seq_len(n_per)),
kelompok = kel_lab[g],
usia = sample(20:55,n_per,replace=TRUE),
jk = sample(c("L","P"),n_per,replace=TRUE,prob=c(.65,.35)),
round(y,1)
)
}) |> bind_rows()
dat_wide$kelompok <- factor(dat_wide$kelompok,levels=kel_lab)
dat_wide$id <- factor(dat_wide$id)
dat_long <- dat_wide |>
pivot_longer(starts_with("SOP_M"),names_to="waktu",values_to="skor") |>
mutate(
waktu=factor(waktu,levels=paste0("SOP_M",minggu),labels=paste0("M",minggu)),
minggu=as.numeric(sub("M","",waktu))
)
head(dat_wide)
## id kelompok usia jk SOP_M0 SOP_M4 SOP_M8 SOP_M12
## 1 K0101 Kontrol 51 L 64.0 66.6 69.5 69.6
## 2 K0102 Kontrol 26 L 62.3 63.8 66.2 67.5
## 3 K0103 Kontrol 40 L 60.9 66.8 61.7 71.3
## 4 K0104 Kontrol 39 P 67.7 71.4 79.7 75.7
## 5 K0105 Kontrol 23 L 77.0 77.3 81.0 86.7
## 6 K0106 Kontrol 21 L 72.4 72.8 72.0 72.3
head(dat_long)
## # A tibble: 6 Ă— 7
## id kelompok usia jk waktu skor minggu
## <fct> <fct> <int> <chr> <fct> <dbl> <dbl>
## 1 K0101 Kontrol 51 L M0 64 0
## 2 K0101 Kontrol 51 L M4 66.6 4
## 3 K0101 Kontrol 51 L M8 69.5 8
## 4 K0101 Kontrol 51 L M12 69.6 12
## 5 K0102 Kontrol 26 L M0 62.3 0
## 6 K0102 Kontrol 26 L M4 63.8 4
str(dat_long)
## tibble [360 Ă— 7] (S3: tbl_df/tbl/data.frame)
## $ id : Factor w/ 90 levels "K0101","K0102",..: 1 1 1 1 2 2 2 2 3 3 ...
## $ kelompok: Factor w/ 3 levels "Kontrol","Video",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ usia : int [1:360] 51 51 51 51 26 26 26 26 40 40 ...
## $ 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 ...
## $ skor : num [1:360] 64 66.6 69.5 69.6 62.3 63.8 66.2 67.5 60.9 66.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(skor,type="mean_sd")
desk
## # A tibble: 12 Ă— 6
## kelompok waktu variable n mean sd
## <fct> <fct> <fct> <dbl> <dbl> <dbl>
## 1 Kontrol M0 skor 30 68.3 6.99
## 2 Kontrol M4 skor 30 68.9 7.58
## 3 Kontrol M8 skor 30 69.8 7.10
## 4 Kontrol M12 skor 30 69.9 7.65
## 5 Video M0 skor 30 67.8 5.95
## 6 Video M4 skor 30 75.0 7.72
## 7 Video M8 skor 30 77.4 7.80
## 8 Video M12 skor 30 80.0 7.51
## 9 Video+Simulasi M0 skor 30 69.2 7.02
## 10 Video+Simulasi M4 skor 30 77.0 6.81
## 11 Video+Simulasi M8 skor 30 83.3 6.88
## 12 Video+Simulasi M12 skor 30 86.3 10.0
S <- cov(dat_wide[,paste0("SOP_M",minggu)])
R <- cor(dat_wide[,paste0("SOP_M",minggu)])
round(S,1); round(R,2)
## SOP_M0 SOP_M4 SOP_M8 SOP_M12
## SOP_M0 43.9 34.0 33.1 35.7
## SOP_M4 34.0 65.2 59.2 69.3
## SOP_M8 33.1 59.2 82.5 87.7
## SOP_M12 35.7 69.3 87.7 116.6
## SOP_M0 SOP_M4 SOP_M8 SOP_M12
## SOP_M0 1.00 0.64 0.55 0.50
## SOP_M4 0.64 1.00 0.81 0.79
## SOP_M8 0.55 0.81 1.00 0.89
## SOP_M12 0.50 0.79 0.89 1.00
pasangan <- combn(paste0("SOP_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)
## SOP_M0 - SOP_M4 SOP_M0 - SOP_M8 SOP_M0 - SOP_M12 SOP_M4 - SOP_M8
## 41.1 60.2 89.2 29.3
## SOP_M4 - SOP_M12 SOP_M8 - SOP_M12
## 43.2 23.5
p_profil <- ggplot(dat_long,aes(minggu,skor,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 kepatuhan SOP",colour="Kelompok",
title="Profil rerata skor SOP (±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.

p_spag <- ggplot(dat_long,aes(minggu,skor,group=id)) +
geom_line(alpha=.3) +
stat_summary(aes(group=kelompok),fun=mean,geom="line",
linewidth=1.2) +
facet_wrap(~kelompok) +
scale_x_continuous(breaks=minggu) +
labs(x="Minggu ke-",y="Skor SOP",title="Lintasan individu dan rerata kelompok")
p_spag

# 3. REPEATED MEASURE ANOVA SATU ARAH
# Pertanyaan: apakah skor kepatuhan SOP berubah selama 12 minggu
# pada kelompok Video+Simulasi?
d1 <- droplevels(filter(dat_long,kelompok=="Video+Simulasi"))
d1w <- filter(dat_wide,kelompok=="Video+Simulasi")
# 3a. Uji asumsi
d1 |> group_by(waktu) |> identify_outliers(skor)
## [1] waktu id kelompok usia jk skor minggu
## [8] is.outlier is.extreme
## <0 rows> (or 0-length row.names)
d1 |> group_by(waktu) |> shapiro_test(skor)
## # A tibble: 4 Ă— 4
## waktu variable statistic p
## <fct> <chr> <dbl> <dbl>
## 1 M0 skor 0.964 0.395
## 2 M4 skor 0.980 0.832
## 3 M8 skor 0.980 0.831
## 4 M12 skor 0.927 0.0409
ggpubr::ggqqplot(d1,"skor",facet.by="waktu")

aov1_rs <- anova_test(data=d1,dv=skor,wid=id,within=waktu,effect.size="pes")
aov1_rs
## ANOVA Table (type III tests)
##
## $ANOVA
## Effect DFn DFd F p p<.05 pes
## 1 waktu 3 87 110.982 1.22e-29 * 0.793
##
## $`Mauchly's Test for Sphericity`
## Effect W p p<.05
## 1 waktu 0.637 0.029 *
##
## $`Sphericity Corrections`
## Effect GGe DF[GG] p[GG] p[GG]<.05 HFe DF[HF] p[HF]
## 1 waktu 0.796 2.39, 69.27 4.35e-24 * 0.873 2.62, 75.91 3.61e-26
## p[HF]<.05
## 1 *
get_anova_table(aov1_rs,correction="auto")
## ANOVA Table (type III tests)
##
## Effect DFn DFd F p p<.05 pes
## 1 waktu 2.39 69.27 110.982 4.35e-24 * 0.793
# 3b. ANOVA + koreksi GG/HF
aov1 <- aov_ez(id="id",dv="skor",data=d1,within="waktu",
anova_table=list(es=c("ges","pes"),correction="GG"))
aov1
## Anova Table (Type 3 tests)
##
## Response: skor
## Effect df MSE F ges pes p.value
## 1 waktu 2.39, 69.27 19.48 110.98 *** .423 .793 <.001
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1
##
## Sphericity correction method: GG
summary(aov1)
##
## Univariate Type III Repeated-Measures ANOVA Assuming Sphericity
##
## Sum Sq num Df Error SS den Df F value Pr(>F)
## (Intercept) 747972 1 5708.1 29 3800.07 < 2.2e-16 ***
## waktu 5164 3 1349.4 87 110.98 < 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.63727 0.028747
##
##
## Greenhouse-Geisser and Huynh-Feldt Corrections
## for Departure from Sphericity
##
## GG eps Pr(>F[GG])
## waktu 0.79622 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## HF eps Pr(>F[HF])
## waktu 0.8725611 3.611093e-26
eta_squared(aov1,partial=TRUE)
## # Effect Size for ANOVA (Type III)
##
## Parameter | Eta2 (partial) | 95% CI
## -----------------------------------------
## waktu | 0.79 | [0.73, 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.41 | [0.27, 1.00]
##
## - One-sided CIs: upper bound fixed at [1.00].
# 3c. Pendekatan multivariat
aov1$Anova
##
## Type III Repeated Measures MANOVA Tests: Pillai test statistic
## Df test stat approx F num Df den Df Pr(>F)
## (Intercept) 1 0.99243 3800.1 1 29 < 2.2e-16 ***
## waktu 1 0.92859 117.0 3 27 1.382e-15 ***
## ---
## 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 69.2 1.28 29 66.6 71.8
## M4 77.0 1.24 29 74.5 79.6
## M8 83.3 1.26 29 80.7 85.9
## M12 86.3 1.83 29 82.6 90.1
##
## Confidence level used: 0.95
pairs(em1,adjust="bonferroni")
## contrast estimate SE df t.ratio p.value
## M0 - M4 -7.84 0.951 29 -8.249 <0.0001
## M0 - M8 -14.11 0.732 29 -19.279 <0.0001
## M0 - M12 -17.13 1.260 29 -13.639 <0.0001
## M4 - M8 -6.26 0.907 29 -6.905 <0.0001
## M4 - M12 -9.29 1.180 29 -7.870 <0.0001
## M8 - M12 -3.02 0.986 29 -3.066 0.0280
##
## P value adjustment: bonferroni method for 6 tests
contrast(em1,"trt.vs.ctrl",ref=1,adjust="holm")
## contrast estimate SE df t.ratio p.value
## M4 - M0 7.84 0.951 29 8.249 <0.0001
## M8 - M0 14.11 0.732 29 19.279 <0.0001
## M12 - M0 17.13 1.260 29 13.639 <0.0001
##
## P value adjustment: holm method for 3 tests
contrast(em1,"poly")
## contrast estimate SE df t.ratio p.value
## linear 57.65 3.90 29 14.801 <0.0001
## quadratic -4.82 1.18 29 -4.068 0.0003
## cubic -1.66 2.97 29 -0.559 0.5807
# 3e. Alternatif nonparametrik
friedman_test(d1,skor~waktu|id)
## # A tibble: 1 Ă— 6
## .y. n statistic df p method
## * <chr> <int> <dbl> <dbl> <dbl> <chr>
## 1 skor 30 69.6 3 5.10e-15 Friedman test
friedman_effsize(d1,skor~waktu|id)
## # A tibble: 1 Ă— 5
## .y. n effsize method magnitude
## * <chr> <int> <dbl> <chr> <ord>
## 1 skor 30 0.774 Kendall W large
d1 |> wilcox_test(skor~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 skor M0 M4 30 30 9 0.0000000615 3.69e-7 ****
## 2 skor M0 M8 30 30 0 0.00000000186 1.12e-8 ****
## 3 skor M0 M12 30 30 0 0.00000000186 1.12e-8 ****
## 4 skor M4 M8 30 30 15.5 0.000000264 1.59e-6 ****
## 5 skor M4 M12 30 30 16.5 0.000000322 1.93e-6 ****
## 6 skor M8 M12 30 30 95 0.00374 2.24e-2 *
# 4. MIXED DESIGN ANOVA
# Pertanyaan: apakah pola perubahan skor SOP berbeda antarkelompok?
# 4a. Uji asumsi
dat_long |> group_by(kelompok,waktu) |> identify_outliers(skor)
## # A tibble: 2 Ă— 9
## kelompok waktu id usia jk skor minggu is.outlier is.extreme
## <fct> <fct> <fct> <int> <chr> <dbl> <dbl> <lgl> <lgl>
## 1 Kontrol M8 K0120 31 L 86.7 8 TRUE FALSE
## 2 Video M0 K0229 25 L 86 0 TRUE FALSE
dat_long |> group_by(kelompok,waktu) |> shapiro_test(skor)
## # A tibble: 12 Ă— 5
## kelompok waktu variable statistic p
## <fct> <fct> <chr> <dbl> <dbl>
## 1 Kontrol M0 skor 0.934 0.0646
## 2 Kontrol M4 skor 0.981 0.855
## 3 Kontrol M8 skor 0.984 0.914
## 4 Kontrol M12 skor 0.976 0.713
## 5 Video M0 skor 0.939 0.0853
## 6 Video M4 skor 0.983 0.907
## 7 Video M8 skor 0.952 0.190
## 8 Video M12 skor 0.984 0.928
## 9 Video+Simulasi M0 skor 0.964 0.395
## 10 Video+Simulasi M4 skor 0.980 0.832
## 11 Video+Simulasi M8 skor 0.980 0.831
## 12 Video+Simulasi M12 skor 0.927 0.0409
ggpubr::ggqqplot(dat_long,"skor",ggtheme=theme_bw()) +
facet_grid(waktu~kelompok)

dat_long |> group_by(waktu) |> levene_test(skor~kelompok)
## # A tibble: 4 Ă— 5
## waktu df1 df2 statistic p
## <fct> <int> <int> <dbl> <dbl>
## 1 M0 2 87 1.71 0.187
## 2 M4 2 87 0.287 0.751
## 3 M8 2 87 0.141 0.869
## 4 M12 2 87 2.98 0.0562
box_m(dat_wide[,paste0("SOP_M",minggu)],dat_wide$kelompok)
## # A tibble: 1 Ă— 4
## statistic p.value parameter method
## <dbl> <dbl> <dbl> <chr>
## 1 27.1 0.132 20 Box's M-test for Homogeneity of Covariance Matric…
# 4b. ANOVA campuran
aov2 <- aov_ez(id="id",dv="skor",data=dat_long,
between="kelompok",within="waktu",
anova_table=list(es=c("ges","pes"),correction="GG"))
aov2
## Anova Table (Type 3 tests)
##
## Response: skor
## Effect df MSE F ges pes p.value
## 1 kelompok 2, 87 175.89 16.35 *** .228 .273 <.001
## 2 waktu 2.59, 225.42 18.42 114.90 *** .220 .569 <.001
## 3 kelompok:waktu 5.18, 225.42 18.42 23.26 *** .102 .348 <.001
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1
##
## Sphericity correction method: GG
summary(aov2)
##
## Univariate Type III Repeated-Measures ANOVA Assuming Sphericity
##
## Sum Sq num Df Error SS den Df F value Pr(>F)
## (Intercept) 1992596 1 15302.3 87 11328.770 < 2.2e-16 ***
## kelompok 5752 2 15302.3 87 16.351 9.37e-07 ***
## waktu 5485 3 4153.2 261 114.897 < 2.2e-16 ***
## kelompok:waktu 2220 6 4153.2 261 23.257 < 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.79822 0.0016768
## kelompok:waktu 0.79822 0.0016768
##
##
## Greenhouse-Geisser and Huynh-Feldt Corrections
## for Departure from Sphericity
##
## GG eps Pr(>F[GG])
## waktu 0.86368 < 2.2e-16 ***
## kelompok:waktu 0.86368 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## HF eps Pr(>F[HF])
## waktu 0.8925231 1.213461e-42
## kelompok:waktu 0.8925231 7.444534e-20
eta_squared(aov2,partial=TRUE)
## # Effect Size for ANOVA (Type III)
##
## Parameter | Eta2 (partial) | 95% CI
## ----------------------------------------------
## kelompok | 0.27 | [0.14, 1.00]
## waktu | 0.57 | [0.51, 1.00]
## kelompok:waktu | 0.35 | [0.27, 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.25 | [0.13, 1.00]
## waktu | 0.22 | [0.14, 1.00]
## kelompok:waktu | 0.10 | [0.03, 1.00]
##
## - One-sided CIs: upper bound fixed at [1.00].
afex_plot(aov2,x="waktu",trace="kelompok",error="within",
mapping=c("colour","shape","linetype")) +
labs(y="Skor SOP",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 & post hoc
em2 <- emmeans(aov2,~waktu|kelompok)
joint_tests(aov2,by="kelompok")
## Warning in pf(conf$F.ratio, conf$df1, conf$df2, lower.tail = FALSE): NaNs
## produced
## kelompok = Kontrol:
## model term df1 df2 F.ratio p.value
## waktu 3 87 0.767 0.5156
##
## kelompok = Video:
## model term df1 df2 F.ratio p.value
## waktu 3 87 34.597 <0.0001
##
## kelompok = Video+Simulasi:
## model term df1 df2 F.ratio p.value
## waktu 3 87 71.908 <0.0001
joint_tests(aov2,by="waktu")
## waktu = M0:
## model term df1 df2 F.ratio p.value
## kelompok 2 87 0.350 0.7059
##
## waktu = M4:
## model term df1 df2 F.ratio p.value
## kelompok 2 87 9.797 0.0001
##
## waktu = M8:
## model term df1 df2 F.ratio p.value
## kelompok 2 87 25.937 <0.0001
##
## waktu = M12:
## model term df1 df2 F.ratio p.value
## kelompok 2 87 28.793 <0.0001
contrast(em2,"trt.vs.ctrl",ref=1,adjust="holm")
## kelompok = Kontrol:
## contrast estimate SE df t.ratio p.value
## M4 - M0 0.597 1.02 87 0.588 0.5583
## M8 - M0 1.497 1.05 87 1.420 0.4774
## M12 - M0 1.543 1.26 87 1.227 0.4774
##
## kelompok = Video:
## contrast estimate SE df t.ratio p.value
## M4 - M0 7.203 1.02 87 7.094 <0.0001
## M8 - M0 9.687 1.05 87 9.192 <0.0001
## M12 - M0 12.203 1.26 87 9.704 <0.0001
##
## kelompok = Video+Simulasi:
## contrast estimate SE df t.ratio p.value
## M4 - M0 7.843 1.02 87 7.724 <0.0001
## M8 - M0 14.107 1.05 87 13.386 <0.0001
## M12 - M0 17.130 1.26 87 13.621 <0.0001
##
## P value adjustment: holm method for 3 tests
em2b <- emmeans(aov2,~kelompok|waktu)
pairs(em2b,adjust="tukey")
## waktu = M0:
## contrast estimate SE df t.ratio p.value
## Kontrol - Video 0.56 1.72 87 0.325 0.9435
## Kontrol - (Video+Simulasi) -0.87 1.72 87 -0.505 0.8692
## Video - (Video+Simulasi) -1.43 1.72 87 -0.830 0.6856
##
## waktu = M4:
## contrast estimate SE df t.ratio p.value
## Kontrol - Video -6.05 1.91 87 -3.173 0.0059
## Kontrol - (Video+Simulasi) -8.12 1.91 87 -4.259 0.0002
## Video - (Video+Simulasi) -2.07 1.91 87 -1.086 0.5251
##
## waktu = M8:
## contrast estimate SE df t.ratio p.value
## Kontrol - Video -7.63 1.88 87 -4.065 0.0003
## Kontrol - (Video+Simulasi) -13.48 1.88 87 -7.182 <0.0001
## Video - (Video+Simulasi) -5.85 1.88 87 -3.117 0.0069
##
## waktu = M12:
## contrast estimate SE df t.ratio p.value
## Kontrol - Video -10.10 2.19 87 -4.618 <0.0001
## Kontrol - (Video+Simulasi) -16.46 2.19 87 -7.524 <0.0001
## Video - (Video+Simulasi) -6.36 2.19 87 -2.906 0.0128
##
## P value adjustment: tukey method for comparing a family of 3 estimates
# 4d. Kontras interaksi: perubahan M12-M0 antarkelompok
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 - Video -10.66 1.78 87 -5.994 <0.0001
## M12-M0 Kontrol - (Video+Simulasi) -15.59 1.78 87 -8.764 <0.0001
## M12-M0 Video - (Video+Simulasi) -4.93 1.78 87 -2.770 0.0068
##
## P value adjustment: holm method for 3 tests
contrast(em2,"poly")[c(1,4,7)]
## contrast kelompok estimate SE df t.ratio p.value
## linear Kontrol 5.53 4.04 87 1.370 0.1741
## linear Video 39.09 4.04 87 9.688 <0.0001
## linear Video+Simulasi 57.65 4.04 87 14.288 <0.0001
tren_int <- summary(
contrast(em_full,interaction=c(waktu="poly",kelompok="pairwise"),
adjust="none")
)
tren_lin <- subset(tren_int,waktu_poly=="linear")
tren_lin$p.holm <- p.adjust(tren_lin$p.value,"holm")
tren_lin
## waktu_poly kelompok_pairwise estimate SE df t.ratio
## 1 linear Kontrol - Video -33.56333 5.706644 87 -5.881448
## 4 linear Kontrol - (Video+Simulasi) -52.12333 5.706644 87 -9.133797
## 7 linear Video - (Video+Simulasi) -18.56000 5.706644 87 -3.252349
## p.value p.holm
## 1 7.382172e-08 1.476434e-07
## 4 2.389727e-14 7.169180e-14
## 7 1.629722e-03 1.629722e-03
# 5. PEMBANDING: LINEAR MIXED MODEL (LMM)
lmm1 <- lmer(skor~kelompok*waktu+(1|id),data=dat_long,REML=TRUE)
lmm2 <- lmer(skor~kelompok*waktu+(1+minggu|id),data=dat_long,REML=TRUE)
anova(lmm1,lmm2,refit=FALSE)
## Data: dat_long
## Models:
## lmm1: skor ~ kelompok * waktu + (1 | id)
## lmm2: skor ~ kelompok * waktu + (1 + minggu | id)
## npar AIC BIC logLik -2*log(L) Chisq Df Pr(>Chisq)
## lmm1 14 2245.5 2299.9 -1108.8 2217.5
## lmm2 16 2224.2 2286.3 -1096.1 2192.2 25.322 2 3.172e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
anova(lmm2,ddf="Kenward-Roger")
## Type III Analysis of Variance Table with Kenward-Roger's method
## Sum Sq Mean Sq NumDF DenDF F value Pr(>F)
## kelompok 381.19 190.60 2 87.00 16.351 9.370e-07 ***
## waktu 2750.82 916.94 3 185.37 78.301 < 2.2e-16 ***
## kelompok:waktu 1125.87 187.64 6 206.40 16.006 4.337e-15 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
performance::icc(lmm1)
## # Intraclass Correlation Coefficient
##
## Adjusted ICC: 0.715
## Unadjusted ICC: 0.428
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))
# Simulasi 30 nilai hilang (MCAR) untuk menunjukkan keunggulan LMM
set.seed(1)
dat_miss <- dat_long
dat_miss$skor[sample(which(dat_miss$waktu!="M0"),30)] <- NA
lmm_miss <- lmer(skor~kelompok*waktu+(1+minggu|id),data=dat_miss,
control=lmerControl(optimizer="bobyqa"))
anova(lmm_miss,ddf="Kenward-Roger")
## Type III Analysis of Variance Table with Kenward-Roger's method
## Sum Sq Mean Sq NumDF DenDF F value Pr(>F)
## kelompok 353.43 176.72 2 86.969 16.140 1.093e-06 ***
## waktu 2391.94 797.31 3 168.298 72.476 < 2.2e-16 ***
## kelompok:waktu 935.45 155.91 6 185.950 14.156 2.960e-13 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
n_distinct(dat_miss$id[is.na(dat_miss$skor)])
## [1] 25
# 6. MENYIMPAN DATA & RINGKASAN
write.csv(dat_wide,"data_kasus_baru_wide.csv",row.names=FALSE)
write.csv(dat_long,"data_kasus_baru_long.csv",row.names=FALSE)
saveRDS(list(wide=dat_wide,long=dat_long,anova=aov2,lmm=lmm2),
"hasil_repeated_measure_kasus_baru.rds")