##..............................................................................
#NAMA : WULANDARI
#NIM : 2611018022
##..............................................................................
#PERUBAHAN HbA1c (%) PADA PASIEN DIABETES TIPE 2
#DENGAN TIGA KELOMPOK INTERVENSI SELAMA 3 BULAN
##..............................................................................
suppressPackageStartupMessages({
library(readxl)
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
library(performance)
library(ggpubr)
})
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))
data_wide <- read_excel("D:/BIOSTATISTIK/Data_Eksperimen_DM_Wide.xlsx", sheet = "Dta DM_Wide")
View(data_wide)
str(data_wide)
## tibble [90 × 8] (S3: tbl_df/tbl/data.frame)
## $ ID_Responden : chr [1:90] "P001" "P002" "P003" "P004" ...
## $ Umur_Tahun : num [1:90] 46 59 54 50 47 60 46 65 58 62 ...
## $ JK : chr [1:90] "P" "P" "P" "L" ...
## $ Kelompok_Perlakuan: chr [1:90] "Kelompok A (Diet & Olahraga)" "Kelompok A (Diet & Olahraga)" "Kelompok A (Diet & Olahraga)" "Kelompok A (Diet & Olahraga)" ...
## $ Pemeriksaan_bln0 : num [1:90] 8.3 9.4 9 8.2 8.6 8.5 9.4 9.2 9 8.6 ...
## $ Pemeriksaan_bln1 : num [1:90] 8 9.2 8.8 7.8 8.4 8.3 9.2 8.8 8.7 8.4 ...
## $ Pemeriksaan_bln2 : num [1:90] 7.8 8.9 8.7 7.6 8.2 8.2 8.9 8.6 8.5 8.2 ...
## $ Pemeriksaan_bln3 : num [1:90] 7.5 8.7 8.4 7.5 8 7.9 8.7 8.5 8.2 8 ...
data_wide <- data_wide %>%
mutate(
id = factor(ID_Responden),
kelompok = factor(Kelompok_Perlakuan,
levels = c("Kelompok A (Diet & Olahraga)",
"Kelompok B (Metformin Standar)",
"Kelompok C (Metformin + Herbal)")),
umur = as.numeric(Umur_Tahun),
jk = factor(JK)
)
data_wide %>% count(kelompok)
## # A tibble: 3 × 2
## kelompok n
## <fct> <int>
## 1 Kelompok A (Diet & Olahraga) 30
## 2 Kelompok B (Metformin Standar) 30
## 3 Kelompok C (Metformin + Herbal) 30
data_long <- data_wide %>%
pivot_longer(
cols = starts_with("Pemeriksaan_bln"),
names_to = "waktu",
values_to = "pemeriksaan"
) %>%
mutate(
waktu = factor(waktu,
levels = c("Pemeriksaan_bln0", "Pemeriksaan_bln1",
"Pemeriksaan_bln2", "Pemeriksaan_bln3"),
labels = c("Bln-0", "Bln-1", "Bln-2", "Bln-3")),
bulan = as.numeric(sub("Bln", "", waktu))
)
head(data_long)
## # A tibble: 6 × 11
## ID_Responden Umur_Tahun JK Kelompok_Perlakuan id kelompok umur jk
## <chr> <dbl> <chr> <chr> <fct> <fct> <dbl> <fct>
## 1 P001 46 P Kelompok A (Diet & O… P001 Kelompo… 46 P
## 2 P001 46 P Kelompok A (Diet & O… P001 Kelompo… 46 P
## 3 P001 46 P Kelompok A (Diet & O… P001 Kelompo… 46 P
## 4 P001 46 P Kelompok A (Diet & O… P001 Kelompo… 46 P
## 5 P002 59 P Kelompok A (Diet & O… P002 Kelompo… 59 P
## 6 P002 59 P Kelompok A (Diet & O… P002 Kelompo… 59 P
## # ℹ 3 more variables: waktu <fct>, pemeriksaan <dbl>, bulan <dbl>
str(data_long)
## tibble [360 × 11] (S3: tbl_df/tbl/data.frame)
## $ ID_Responden : chr [1:360] "P001" "P001" "P001" "P001" ...
## $ Umur_Tahun : num [1:360] 46 46 46 46 59 59 59 59 54 54 ...
## $ JK : chr [1:360] "P" "P" "P" "P" ...
## $ Kelompok_Perlakuan: chr [1:360] "Kelompok A (Diet & Olahraga)" "Kelompok A (Diet & Olahraga)" "Kelompok A (Diet & Olahraga)" "Kelompok A (Diet & Olahraga)" ...
## $ id : Factor w/ 90 levels "P001","P002",..: 1 1 1 1 2 2 2 2 3 3 ...
## $ kelompok : Factor w/ 3 levels "Kelompok A (Diet & Olahraga)",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ umur : num [1:360] 46 46 46 46 59 59 59 59 54 54 ...
## $ jk : Factor w/ 2 levels "L","P": 2 2 2 2 2 2 2 2 2 2 ...
## $ waktu : Factor w/ 4 levels "Bln-0","Bln-1",..: 1 2 3 4 1 2 3 4 1 2 ...
## $ pemeriksaan : num [1:360] 8.3 8 7.8 7.5 9.4 9.2 8.9 8.7 9 8.8 ...
## $ bulan : num [1:360] 0 -1 -2 -3 0 -1 -2 -3 0 -1 ...
colSums(is.na(data_wide))
## ID_Responden Umur_Tahun JK Kelompok_Perlakuan
## 0 0 0 0
## Pemeriksaan_bln0 Pemeriksaan_bln1 Pemeriksaan_bln2 Pemeriksaan_bln3
## 0 0 0 0
## id kelompok umur jk
## 0 0 0 0
colSums(is.na(data_long))
## ID_Responden Umur_Tahun JK Kelompok_Perlakuan
## 0 0 0 0
## id kelompok umur jk
## 0 0 0 0
## waktu pemeriksaan bulan
## 0 0 0
data_long %>% count(id, waktu) %>% filter(n != 1)
## # A tibble: 0 × 3
## # ℹ 3 variables: id <fct>, waktu <fct>, n <int>
dim(data_wide)
## [1] 90 12
dim(data_long)
## [1] 360 11
table(data_long$kelompok, data_long$waktu)
##
## Bln-0 Bln-1 Bln-2 Bln-3
## Kelompok A (Diet & Olahraga) 30 30 30 30
## Kelompok B (Metformin Standar) 30 30 30 30
## Kelompok C (Metformin + Herbal) 30 30 30 30
# 1. EKSPLORASI DATA
# 1a. Statistik deskriptif per kelompok dan waktu
deskriptif <- data_long %>%
group_by(kelompok, waktu) %>%
get_summary_stats(pemeriksaan, type = "mean_sd")
deskriptif
## # A tibble: 12 × 6
## kelompok waktu variable n mean sd
## <fct> <fct> <fct> <dbl> <dbl> <dbl>
## 1 Kelompok A (Diet & Olahraga) Bln-0 pemeriksaan 30 8.61 0.566
## 2 Kelompok A (Diet & Olahraga) Bln-1 pemeriksaan 30 8.34 0.57
## 3 Kelompok A (Diet & Olahraga) Bln-2 pemeriksaan 30 8.15 0.573
## 4 Kelompok A (Diet & Olahraga) Bln-3 pemeriksaan 30 7.92 0.594
## 5 Kelompok B (Metformin Standar) Bln-0 pemeriksaan 30 8.52 0.542
## 6 Kelompok B (Metformin Standar) Bln-1 pemeriksaan 30 7.95 0.567
## 7 Kelompok B (Metformin Standar) Bln-2 pemeriksaan 30 7.49 0.554
## 8 Kelompok B (Metformin Standar) Bln-3 pemeriksaan 30 7.18 0.561
## 9 Kelompok C (Metformin + Herbal) Bln-0 pemeriksaan 30 8.24 0.474
## 10 Kelompok C (Metformin + Herbal) Bln-1 pemeriksaan 30 7.45 0.439
## 11 Kelompok C (Metformin + Herbal) Bln-2 pemeriksaan 30 6.85 0.434
## 12 Kelompok C (Metformin + Herbal) Bln-3 pemeriksaan 30 6.40 0.443
# 1b.Rerata perubahan dari baseline
perubahan <- data_wide %>%
mutate(
perubahan_Bln3_Bln0 = Pemeriksaan_bln3 - Pemeriksaan_bln0,
penurunan_Bln0_Bln3 = Pemeriksaan_bln0 - Pemeriksaan_bln3
) %>%
group_by(kelompok) %>%
summarise(
n = n(),
mean_perubahan = mean(perubahan_Bln3_Bln0, na.rm = TRUE),
mean_penurunan = mean(penurunan_Bln0_Bln3, na.rm = TRUE),
sd_penurunan = sd(penurunan_Bln0_Bln3, na.rm = TRUE)
)
perubahan
## # A tibble: 3 × 5
## kelompok n mean_perubahan mean_penurunan sd_penurunan
## <fct> <int> <dbl> <dbl> <dbl>
## 1 Kelompok A (Diet & Olahraga) 30 -0.69 0.69 0.118
## 2 Kelompok B (Metformin Standa… 30 -1.35 1.35 0.161
## 3 Kelompok C (Metformin + Herb… 30 -1.84 1.84 0.192
# 1c. Matriks Kovarians dan korelasi
S <- cov(data_wide[, c("Pemeriksaan_bln0","Pemeriksaan_bln1",
"Pemeriksaan_bln2","Pemeriksaan_bln3")],
use = "complete.obs")
R <- cor(data_wide[, c("Pemeriksaan_bln0","Pemeriksaan_bln1",
"Pemeriksaan_bln2","Pemeriksaan_bln3")],
use = "complete.obs")
round(S, 3)
## Pemeriksaan_bln0 Pemeriksaan_bln1 Pemeriksaan_bln2
## Pemeriksaan_bln0 0.299 0.324 0.342
## Pemeriksaan_bln1 0.324 0.410 0.463
## Pemeriksaan_bln2 0.342 0.463 0.555
## Pemeriksaan_bln3 0.361 0.501 0.606
## Pemeriksaan_bln3
## Pemeriksaan_bln0 0.361
## Pemeriksaan_bln1 0.501
## Pemeriksaan_bln2 0.606
## Pemeriksaan_bln3 0.674
round(R, 3)
## Pemeriksaan_bln0 Pemeriksaan_bln1 Pemeriksaan_bln2
## Pemeriksaan_bln0 1.000 0.925 0.841
## Pemeriksaan_bln1 0.925 1.000 0.972
## Pemeriksaan_bln2 0.841 0.972 1.000
## Pemeriksaan_bln3 0.805 0.953 0.991
## Pemeriksaan_bln3
## Pemeriksaan_bln0 0.805
## Pemeriksaan_bln1 0.953
## Pemeriksaan_bln2 0.991
## Pemeriksaan_bln3 1.000
# 1d. Profile plot rerata ± 95% CI
p_profil <- ggplot(data_long, aes(bulan, pemeriksaan,
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 = .15) +
scale_x_continuous(breaks = 0:3) +
labs(x = "Bulan", y = "Nilai pemeriksaan HbA1c",
colour = "Kelompok", title = "Profil rerata nilai pemeriksaan") +
theme_bw()
p_profil

# 1e. Spaghetti plot
data_long$bulan <- as.numeric(gsub("[^0-9]", "", data_long$bulan))
p_spag <- ggplot(data_long, aes(bulan, pemeriksaan, group = id)) +
geom_line(alpha = .25) +
stat_summary(aes(group = kelompok), fun = mean, geom = "line", linewidth = 1.2) +
facet_wrap(~ kelompok) +
scale_x_continuous(breaks = 0:3, labels = c("0", "1", "2", "3")) +
labs(x = "Bulan ke-", y = "Nilai pemeriksaan HbA1c", title = "Lintasan individu dan rerata kelompok") +
theme_bw()
p_spag

# 2. REPEATED MEASURES ANOVA SATU ARAH
# 2a. Satu kelompok
d1 <- data_long %>%
filter(kelompok == "Kelompok A (Diet & Olahraga)") %>%
droplevels()
d1w <- data_wide %>%
filter(kelompok == "Kelompok A (Diet & Olahraga)") %>%
droplevels()
# 2b. Uji Asumsi ...............................................................
# (i) Uji Outlier Per waktu
d1 %>% group_by(waktu) %>% identify_outliers(pemeriksaan)
## [1] waktu ID_Responden Umur_Tahun JK
## [5] Kelompok_Perlakuan id kelompok umur
## [9] jk pemeriksaan bulan is.outlier
## [13] is.extreme
## <0 rows> (or 0-length row.names)
# (ii) Uji Normalitas per waktu
d1 %>% group_by(waktu) %>% shapiro_test(pemeriksaan)
## # A tibble: 4 × 4
## waktu variable statistic p
## <fct> <chr> <dbl> <dbl>
## 1 Bln-0 pemeriksaan 0.952 0.192
## 2 Bln-1 pemeriksaan 0.961 0.323
## 3 Bln-2 pemeriksaan 0.945 0.123
## 4 Bln-3 pemeriksaan 0.939 0.0847
ggpubr::ggqqplot(d1, "pemeriksaan", facet.by = "waktu")

# (iii) Uji sphericity + RM ANOVA
aov1_rs <- anova_test(
data = d1, dv = pemeriksaan, 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 602.751 4.53e-58 * 0.954
##
## $`Mauchly's Test for Sphericity`
## Effect W p p<.05
## 1 waktu 0.539 0.004 *
##
## $`Sphericity Corrections`
## Effect GGe DF[GG] p[GG] p[GG]<.05 HFe DF[HF] p[HF]
## 1 waktu 0.716 2.15, 62.29 2.83e-42 * 0.775 2.33, 67.43 1.46e-45
## p[HF]<.05
## 1 *
get_anova_table(aov1_rs, correction = "auto") # auto : GG dipakai jika Mauchly p<0.5
## ANOVA Table (type III tests)
##
## Effect DFn DFd F p p<.05 pes
## 1 waktu 2.15 62.29 602.751 2.83e-42 * 0.954
# 2b. Uji ANOVA dengan Afex
aov1 <- aov_ez(
id = "id", dv = "pemeriksaan", data = d1, within = "waktu",
anova_table = list(es = c("ges", "pes"), correction = "GG")
)
aov1
## Anova Table (Type 3 tests)
##
## Response: pemeriksaan
## Effect df MSE F ges pes p.value
## 1 waktu 2.15, 62.29 0.01 602.75 *** .167 .954 <.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) 8182.4 1 38.086 29 6230.37 < 2.2e-16 ***
## waktu 7.7 3 0.371 87 602.75 < 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.53944 0.0043201
##
##
## Greenhouse-Geisser and Huynh-Feldt Corrections
## for Departure from Sphericity
##
## GG eps Pr(>F[GG])
## waktu 0.71595 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## HF eps Pr(>F[HF])
## waktu 0.7750481 1.456296e-45
# (i) Ukuran Efek
eta_squared(aov1, partial = TRUE)
## # Effect Size for ANOVA (Type III)
##
## Parameter | Eta2 (partial) | 95% CI
## -----------------------------------------
## waktu | 0.95 | [0.94, 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.16 | [0.04, 1.00]
##
## - One-sided CIs: upper bound fixed at [1.00].
# 2c. Pendekatan Multivariat
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.99537 6230.4 1 29 < 2.2e-16 ***
## waktu 1 0.97466 346.2 3 27 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# 2d. Post Hoct
em1 <- emmeans(aov1, ~ waktu)
em1
## waktu emmean SE df lower.CL upper.CL
## Bln.0 8.61 0.103 29 8.40 8.82
## Bln.1 8.34 0.104 29 8.13 8.56
## Bln.2 8.15 0.105 29 7.94 8.36
## Bln.3 7.92 0.108 29 7.70 8.15
##
## Confidence level used: 0.95
pairs(em1, adjust = "bonferroni") # semua pasangan waktu (6 perbandingan)
## contrast estimate SE df t.ratio p.value
## Bln.0 - Bln.1 0.270 0.0174 29 15.529 <0.0001
## Bln.0 - Bln.2 0.463 0.0200 29 23.111 <0.0001
## Bln.0 - Bln.3 0.690 0.0216 29 31.902 <0.0001
## Bln.1 - Bln.2 0.193 0.0117 29 16.554 <0.0001
## Bln.1 - Bln.3 0.420 0.0155 29 27.163 <0.0001
## Bln.2 - Bln.3 0.227 0.0126 29 17.954 <0.0001
##
## 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
## Bln.1 - Bln.0 -0.270 0.0174 29 -15.529 <0.0001
## Bln.2 - Bln.0 -0.463 0.0200 29 -23.111 <0.0001
## Bln.3 - Bln.0 -0.690 0.0216 29 -31.902 <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 -2.2633 0.0699 29 -32.384 <0.0001
## quadratic 0.0433 0.0223 29 1.941 0.0620
## cubic -0.1100 0.0340 29 -3.233 0.0030
# 2e. Alternatif nonparametrik..................................................
friedman_test(d1, pemeriksaan ~ waktu | id)
## # A tibble: 1 × 6
## .y. n statistic df p method
## * <chr> <int> <dbl> <dbl> <dbl> <chr>
## 1 pemeriksaan 30 90 3 2.19e-19 Friedman test
friedman_effsize(d1, pemeriksaan ~ waktu | id) # Kendalll's W
## # A tibble: 1 × 5
## .y. n effsize method magnitude
## * <chr> <int> <dbl> <chr> <ord>
## 1 pemeriksaan 30 1 Kendall W large
d1 %>% wilcox_test(pemeriksaan ~ 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 pemeriksaan Bln-0 Bln-1 30 30 465 1.86e-9 1.12e-8 ****
## 2 pemeriksaan Bln-0 Bln-2 30 30 465 1.86e-9 1.12e-8 ****
## 3 pemeriksaan Bln-0 Bln-3 30 30 465 1.86e-9 1.12e-8 ****
## 4 pemeriksaan Bln-1 Bln-2 30 30 465 1.86e-9 1.12e-8 ****
## 5 pemeriksaan Bln-1 Bln-3 30 30 465 1.86e-9 1.12e-8 ****
## 6 pemeriksaan Bln-2 Bln-3 30 30 465 1.86e-9 1.12e-8 ****
# 3. MIXED DESIGN ANOVA
# 3a. uji Asumsi................................................................
# (i) Uji Outlier per sel
data_long |> group_by(kelompok, waktu) |> identify_outliers(pemeriksaan)
## [1] kelompok waktu ID_Responden Umur_Tahun
## [5] JK Kelompok_Perlakuan id umur
## [9] jk pemeriksaan bulan is.outlier
## [13] is.extreme
## <0 rows> (or 0-length row.names)
# (ii) Normalitas per sel
data_long %>%
group_by(kelompok, waktu) %>%
shapiro_test(pemeriksaan)
## # A tibble: 12 × 5
## kelompok waktu variable statistic p
## <fct> <fct> <chr> <dbl> <dbl>
## 1 Kelompok A (Diet & Olahraga) Bln-0 pemeriksaan 0.952 0.192
## 2 Kelompok A (Diet & Olahraga) Bln-1 pemeriksaan 0.961 0.323
## 3 Kelompok A (Diet & Olahraga) Bln-2 pemeriksaan 0.945 0.123
## 4 Kelompok A (Diet & Olahraga) Bln-3 pemeriksaan 0.939 0.0847
## 5 Kelompok B (Metformin Standar) Bln-0 pemeriksaan 0.947 0.139
## 6 Kelompok B (Metformin Standar) Bln-1 pemeriksaan 0.937 0.0739
## 7 Kelompok B (Metformin Standar) Bln-2 pemeriksaan 0.958 0.276
## 8 Kelompok B (Metformin Standar) Bln-3 pemeriksaan 0.961 0.324
## 9 Kelompok C (Metformin + Herbal) Bln-0 pemeriksaan 0.943 0.109
## 10 Kelompok C (Metformin + Herbal) Bln-1 pemeriksaan 0.944 0.119
## 11 Kelompok C (Metformin + Herbal) Bln-2 pemeriksaan 0.960 0.318
## 12 Kelompok C (Metformin + Herbal) Bln-3 pemeriksaan 0.968 0.482
ggpubr::ggqqplot(data_long, "pemeriksaan", ggtheme = theme_bw()) +
facet_grid(waktu ~ kelompok)

# (iii) Homogenitas Varians
data_long %>% group_by(waktu) %>% levene_test(pemeriksaan ~ kelompok)
## # A tibble: 4 × 5
## waktu df1 df2 statistic p
## <fct> <int> <int> <dbl> <dbl>
## 1 Bln-0 2 87 0.825 0.442
## 2 Bln-1 2 87 1.79 0.173
## 3 Bln-2 2 87 1.56 0.216
## 4 Bln-3 2 87 1.53 0.222
# (iv) Homogrnitas matriks kovarians antarkelompok
box_m(
data_wide[, c("Pemeriksaan_bln0","Pemeriksaan_bln1",
"Pemeriksaan_bln2","Pemeriksaan_bln3")],
data_wide$kelompok
)
## # A tibble: 1 × 4
## statistic p.value parameter method
## <dbl> <dbl> <dbl> <chr>
## 1 31.1 0.0537 20 Box's M-test for Homogeneity of Covariance Matric…
# 3b. Mixed Anova...............................................................
aov2 <- aov_ez(
id = "id", dv = "pemeriksaan", data = data_long,
between = "kelompok", within = "waktu",
anova_table = list(es = c("ges", "pes"), correction = "GG")
)
aov2
## Anova Table (Type 3 tests)
##
## Response: pemeriksaan
## Effect df MSE F ges pes p.value
## 1 kelompok 2, 87 1.10 28.76 *** .393 .398 <.001
## 2 waktu 2.20, 191.49 0.01 3540.89 *** .463 .976 <.001
## 3 kelompok:waktu 4.40, 191.49 0.01 245.63 *** .107 .850 <.001
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1
##
## Sphericity correction method: GG
summary(aov2) # Mouchly, 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) 21669.0 1 95.554 87 19729.109 < 2.2e-16 ***
## kelompok 63.2 2 95.554 87 28.755 2.591e-10 ***
## waktu 84.3 3 2.070 261 3540.886 < 2.2e-16 ***
## kelompok:waktu 11.7 6 2.070 261 245.627 < 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.57292 4.0174e-09
## kelompok:waktu 0.57292 4.0174e-09
##
##
## Greenhouse-Geisser and Huynh-Feldt Corrections
## for Departure from Sphericity
##
## GG eps Pr(>F[GG])
## waktu 0.73369 < 2.2e-16 ***
## kelompok:waktu 0.73369 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## HF eps Pr(>F[HF])
## waktu 0.7535227 9.334283e-160
## kelompok:waktu 0.7535227 3.040800e-79
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.99561 19729.1 1 87 < 2.2e-16 ***
## kelompok 2 0.39797 28.8 2 87 2.591e-10 ***
## waktu 1 0.98563 1943.8 3 85 < 2.2e-16 ***
## kelompok:waktu 2 0.97626 27.3 6 172 < 2.2e-16 ***
## ---
## 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 = data_long, dv = pemeriksaan, 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.0 87.00 28.755 2.59e-10 * 0.398
## 2 waktu 2.2 191.49 3540.886 1.25e-155 * 0.976
## 3 kelompok:waktu 4.4 191.49 245.627 3.15e-77 * 0.850
# Ukuran efek
eta_squared(aov2, partial = TRUE)
## # Effect Size for ANOVA (Type III)
##
## Parameter | Eta2 (partial) | 95% CI
## ----------------------------------------------
## kelompok | 0.40 | [0.26, 1.00]
## waktu | 0.98 | [0.97, 1.00]
## kelompok:waktu | 0.85 | [0.83, 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.38 | [0.25, 1.00]
## waktu | 0.46 | [0.39, 1.00]
## kelompok:waktu | 0.11 | [0.04, 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 = "pemeriksaan HbA1c (%)", 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"

# 3c. 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")
## Warning in pf(conf$F.ratio, conf$df1, conf$df2, lower.tail = FALSE): NaNs
## produced
## kelompok = Kelompok A (Diet & Olahraga):
## model term df1 df2 F.ratio p.value
## waktu 3 87 191.223 <0.0001
##
## kelompok = Kelompok B (Metformin Standar):
## model term df1 df2 F.ratio p.value
## waktu 3 87 725.406 <0.0001
##
## kelompok = Kelompok C (Metformin + Herbal):
## model term df1 df2 F.ratio p.value
## waktu 3 87 1345.121 <0.0001
# Efek KELOMPOK pada tiap waktu
joint_tests(aov2, by = "waktu")
## waktu = Bln.0:
## model term df1 df2 F.ratio p.value
## kelompok 2 87 4.074 0.0204
##
## waktu = Bln.1:
## model term df1 df2 F.ratio p.value
## kelompok 2 87 21.690 <0.0001
##
## waktu = Bln.2:
## model term df1 df2 F.ratio p.value
## kelompok 2 87 46.334 <0.0001
##
## waktu = Bln.3:
## model term df1 df2 F.ratio p.value
## kelompok 2 87 60.703 <0.0001
# Post hoc: tiap waktu vs baseline di dalam tiap kelompok
contrast(em2, "trt.vs.ctrl", ref = 1, adjust = "holm")
## kelompok = Kelompok A (Diet & Olahraga):
## contrast estimate SE df t.ratio p.value
## Bln.1 - Bln.0 -0.270 0.0222 87 -12.170 <0.0001
## Bln.2 - Bln.0 -0.463 0.0267 87 -17.366 <0.0001
## Bln.3 - Bln.0 -0.690 0.0293 87 -23.578 <0.0001
##
## kelompok = Kelompok B (Metformin Standar):
## contrast estimate SE df t.ratio p.value
## Bln.1 - Bln.0 -0.570 0.0222 87 -25.692 <0.0001
## Bln.2 - Bln.0 -1.037 0.0267 87 -38.854 <0.0001
## Bln.3 - Bln.0 -1.347 0.0293 87 -46.016 <0.0001
##
## kelompok = Kelompok C (Metformin + Herbal):
## contrast estimate SE df t.ratio p.value
## Bln.1 - Bln.0 -0.793 0.0222 87 -35.759 <0.0001
## Bln.2 - Bln.0 -1.393 0.0267 87 -52.222 <0.0001
## Bln.3 - Bln.0 -1.843 0.0293 87 -62.987 <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 = Bln.0:
## contrast estimate
## Kelompok A (Diet & Olahraga) - Kelompok B (Metformin Standar) 0.090
## Kelompok A (Diet & Olahraga) - (Kelompok C (Metformin + Herbal)) 0.373
## Kelompok B (Metformin Standar) - (Kelompok C (Metformin + Herbal)) 0.283
## SE df t.ratio p.value
## 0.137 87 0.659 0.7876
## 0.137 87 2.735 0.0205
## 0.137 87 2.075 0.1009
##
## waktu = Bln.1:
## contrast estimate
## Kelompok A (Diet & Olahraga) - Kelompok B (Metformin Standar) 0.390
## Kelompok A (Diet & Olahraga) - (Kelompok C (Metformin + Herbal)) 0.897
## Kelompok B (Metformin Standar) - (Kelompok C (Metformin + Herbal)) 0.507
## SE df t.ratio p.value
## 0.137 87 2.857 0.0147
## 0.137 87 6.568 <0.0001
## 0.137 87 3.711 0.0010
##
## waktu = Bln.2:
## contrast estimate
## Kelompok A (Diet & Olahraga) - Kelompok B (Metformin Standar) 0.663
## Kelompok A (Diet & Olahraga) - (Kelompok C (Metformin + Herbal)) 1.303
## Kelompok B (Metformin Standar) - (Kelompok C (Metformin + Herbal)) 0.640
## SE df t.ratio p.value
## 0.135 87 4.899 <0.0001
## 0.135 87 9.626 <0.0001
## 0.135 87 4.727 <0.0001
##
## waktu = Bln.3:
## contrast estimate
## Kelompok A (Diet & Olahraga) - Kelompok B (Metformin Standar) 0.747
## Kelompok A (Diet & Olahraga) - (Kelompok C (Metformin + Herbal)) 1.527
## Kelompok B (Metformin Standar) - (Kelompok C (Metformin + Herbal)) 0.780
## SE df t.ratio p.value
## 0.139 87 5.388 <0.0001
## 0.139 87 11.018 <0.0001
## 0.139 87 5.629 <0.0001
##
## P value adjustment: tukey method for comparing a family of 3 estimates
# 4d. Kontras interaksi -------------------------------------------------------
# Apakah penurunan (Bln3 - Bln0) berbeda antarkelompok? -- inti pertanyaan uji klinis
em_full <- emmeans(aov2, ~ waktu * kelompok)
contrast(em_full, interaction = list(waktu = list("Bln3-Bln0" = c(-1, 0, 0, 1)),
kelompok = "pairwise"),adjust = "holm")
## waktu_custom
## Bln3-Bln0
## Bln3-Bln0
## Bln3-Bln0
## kelompok_pairwise estimate
## Kelompok A (Diet & Olahraga) - Kelompok B (Metformin Standar) 0.657
## Kelompok A (Diet & Olahraga) - (Kelompok C (Metformin + Herbal)) 1.153
## Kelompok B (Metformin Standar) - (Kelompok C (Metformin + Herbal)) 0.497
## SE df t.ratio p.value
## 0.0414 87 15.866 <0.0001
## 0.0414 87 27.867 <0.0001
## 0.0414 87 12.000 <0.0001
##
## 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 Kelompok A (Diet & Olahraga) -2.26 0.0966 87 -23.422 <0.0001
## linear Kelompok B (Metformin Standar) -4.51 0.0966 87 -46.638 <0.0001
## linear Kelompok C (Metformin + Herbal) -6.13 0.0966 87 -63.437 <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
## 1 linear Kelompok A (Diet & Olahraga) - Kelompok B (Metformin Standar)
## 4 linear Kelompok A (Diet & Olahraga) - (Kelompok C (Metformin + Herbal))
## 7 linear Kelompok B (Metformin Standar) - (Kelompok C (Metformin + Herbal))
## estimate SE df t.ratio p.value p.holm
## 1 2.243333 0.1366578 87 16.41570 2.217873e-28 4.435747e-28
## 4 3.866667 0.1366578 87 28.29452 1.188141e-45 3.564422e-45
## 7 1.623333 0.1366578 87 11.87882 6.643211e-20 6.643211e-20
# 5. PEMBANDING: LINEAR MIXED MODEL (LMM)
# Tidak mensyaratkan sfierisitas, menampung data hilang (MAR) dan waktu
# pengukuran yang tidak seragam.
lmm1 <- lmer(
pemeriksaan ~ kelompok * waktu + (1 | id),
data = data_long, REML = TRUE
)
summary(lmm1)
## Linear mixed model fit by REML. t-tests use Satterthwaite's method [
## lmerModLmerTest]
## Formula: pemeriksaan ~ kelompok * waktu + (1 | id)
## Data: data_long
##
## REML criterion at convergence: -208.8
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.30820 -0.57911 0.05473 0.49325 2.12640
##
## Random effects:
## Groups Name Variance Std.Dev.
## id (Intercept) 0.272599 0.52211
## Residual 0.007932 0.08906
## Number of obs: 360, groups: id, 90
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 7.75833 0.05523 87.00000 140.460 < 2e-16 ***
## kelompok1 0.49917 0.07811 87.00000 6.390 7.92e-09 ***
## kelompok2 0.02667 0.07811 87.00000 0.341 0.73364
## waktu1 0.70056 0.00813 261.00000 86.169 < 2e-16 ***
## waktu2 0.15611 0.00813 261.00000 19.202 < 2e-16 ***
## waktu3 -0.26389 0.00813 261.00000 -32.459 < 2e-16 ***
## kelompok1:waktu1 -0.34472 0.01150 261.00000 -29.982 < 2e-16 ***
## kelompok2:waktu1 0.03778 0.01150 261.00000 3.286 0.00116 **
## kelompok1:waktu2 -0.07028 0.01150 261.00000 -6.112 3.56e-09 ***
## kelompok2:waktu2 0.01222 0.01150 261.00000 1.063 0.28875
## kelompok1:waktu3 0.15639 0.01150 261.00000 13.602 < 2e-16 ***
## kelompok2:waktu3 -0.03444 0.01150 261.00000 -2.996 0.00300 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) klmpk1 klmpk2 waktu1 waktu2 waktu3 klm1:1 klm2:1 klm1:2
## kelompok1 0.000
## kelompok2 0.000 -0.500
## waktu1 0.000 0.000 0.000
## waktu2 0.000 0.000 0.000 -0.333
## waktu3 0.000 0.000 0.000 -0.333 -0.333
## klmpk1:wkt1 0.000 0.000 0.000 0.000 0.000 0.000
## klmpk2:wkt1 0.000 0.000 0.000 0.000 0.000 0.000 -0.500
## klmpk1:wkt2 0.000 0.000 0.000 0.000 0.000 0.000 -0.333 0.167
## klmpk2:wkt2 0.000 0.000 0.000 0.000 0.000 0.000 0.167 -0.333 -0.500
## klmpk1:wkt3 0.000 0.000 0.000 0.000 0.000 0.000 -0.333 0.167 -0.333
## klmpk2:wkt3 0.000 0.000 0.000 0.000 0.000 0.000 0.167 -0.333 0.167
## klm2:2 klm1:3
## kelompok1
## kelompok2
## waktu1
## waktu2
## waktu3
## klmpk1:wkt1
## klmpk2:wkt1
## klmpk1:wkt2
## klmpk2:wkt2
## klmpk1:wkt3 0.167
## klmpk2:wkt3 -0.333 -0.500
lmm2 <- lmer(pemeriksaan ~ kelompok * waktu + (1 + bulan | id), data = data_long, REML = TRUE)
anova(lmm1, lmm2, refit = FALSE) # uji rasio kemungkinan struktur acak
## Data: data_long
## Models:
## lmm1: pemeriksaan ~ kelompok * waktu + (1 | id)
## lmm2: pemeriksaan ~ kelompok * waktu + (1 + bulan | id)
## npar AIC BIC logLik -2*log(L) Chisq Df Pr(>Chisq)
## lmm1 14 -180.77 -126.36 104.38 -208.77
## lmm2 16 -211.55 -149.38 121.78 -243.55 34.786 2 2.794e-08 ***
## ---
## 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 0.2815 0.1407 2 87.00 28.755 2.591e-10 ***
## waktu 30.1249 10.0416 3 185.37 2042.303 < 2.2e-16 ***
## kelompok:waktu 4.3318 0.7220 6 206.40 146.674 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
performance::icc(lmm1) # korelasi intrakelas
## # Intraclass Correlation Coefficient
##
## Adjusted ICC: 0.972
## Unadjusted ICC: 0.377
# 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)
# JIka ada missing value
# untuk menunjukkan keunggulan LMM
# contoh jika ada missing value
data_long_miss <- data_long
lmm_miss <- lmer(
pemeriksaan ~ kelompok * waktu + (1 + bulan | id),
data = data_long_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 0.2815 0.1407 2 87.00 28.755 2.591e-10 ***
## waktu 30.1245 10.0415 3 185.37 2042.284 < 2.2e-16 ***
## kelompok:waktu 4.3318 0.7220 6 206.40 146.673 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# 4. SIMPAN DATA & SESSION INFO
write.csv(data_wide, "Data_Eksperimen_DM_Wide.csv", row.names = FALSE)
write.csv(data_long, "data_eksperimen_DM_long.csv", row.names = FALSE)