# TUGAS BIOSTATISTIKA INTERMEDIATE
# ANALISIS PENGUKURAN BERULANG HEMOGLOBIN (Hb)
# Disesuaikan untuk data long format: id, kelompok, usia, waktu, Hb
# Nama : Prisceilla Cindy Samosir
# NIM : 2611018010
# ========================= PARAMETER ANALISIS ==========================
FILE_DATA <- "data_hemoglobin_anemia_long.csv"
FOLDER_HASIL <- "hasil_analisis_hb"
KELOMPOK_FOKUS <- "Pemberian TTD + ANC"
INSTALL_PAKET_OTOMATIS <- TRUE
BUKA_HTML_OTOMATIS <- TRUE
TAMPILKAN_GRAFIK_RSTUDIO <- TRUE
# ============================== FUNGSI =================================
get_script_dir <- function() {
# Aman untuk source(), run-by-line di RStudio, dan eksekusi dari Rscript.
args <- commandArgs(trailingOnly = FALSE)
file_arg <- args[grepl("^--file=", args)]
if (length(file_arg) > 0L) {
path <- sub("^--file=", "", file_arg[1])
if (nzchar(path)) {
return(dirname(normalizePath(path, winslash = "/", mustWork = FALSE)))
}
}
if (requireNamespace("rstudioapi", quietly = TRUE) && rstudioapi::isAvailable()) {
p <- tryCatch(rstudioapi::getSourceEditorContext()$path, error = function(e) "")
if (nzchar(p)) return(dirname(normalizePath(p, winslash = "/", mustWork = FALSE)))
}
# Fallback terakhir: folder kerja saat ini.
getwd()
}
cek_paket <- function(paket) {
belum <- paket[!vapply(paket, requireNamespace, logical(1), quietly = TRUE)]
if (length(belum)) {
if (!INSTALL_PAKET_OTOMATIS) {
stop("Paket belum tersedia: ", paste(belum, collapse = ", "))
}
message("Menginstal paket: ", paste(belum, collapse = ", "))
install.packages(belum, repos = "https://cloud.r-project.org")
}
gagal <- paket[!vapply(paket, requireNamespace, logical(1), quietly = TRUE)]
if (length(gagal)) stop("Instalasi gagal: ", paste(gagal, collapse = ", "))
}
fp <- function(p) {
if (is.na(p)) return("tidak tersedia")
if (p < .001) "< 0,001" else paste0("= ", formatC(p, digits = 3, format = "f", decimal.mark = ","))
}
ci_mean <- function(x) {
x <- x[!is.na(x)]
n <- length(x)
if (n == 0L) {
return(data.frame(n = 0L, mean = NA_real_, sd = NA_real_, median = NA_real_,
min = NA_real_, max = NA_real_, se = NA_real_,
lower_ci = NA_real_, upper_ci = NA_real_))
}
mu <- mean(x)
sdv <- if (n > 1L) sd(x) else NA_real_
se <- if (n > 1L) sdv / sqrt(n) else NA_real_
ci <- if (n > 1L) qt(.975, df = n - 1L) * se else NA_real_
data.frame(
n = n,
mean = mu,
sd = sdv,
median = median(x),
min = min(x),
max = max(x),
se = se,
lower_ci = if (is.na(ci)) NA_real_ else mu - ci,
upper_ci = if (is.na(ci)) NA_real_ else mu + ci
)
}
safe_print <- function(x) {
teks <- capture.output(print(x))
cat(paste(teks, collapse = "\n"), "\n")
invisible(teks)
}
# ======================= JALANKAN ANALISIS ============================
jalankan_analisis <- function() {
waktu_mulai <- Sys.time()
paket <- c(
"dplyr", "tidyr", "ggplot2", "afex", "emmeans", "rstatix", "car",
"effectsize", "lme4", "lmerTest", "pbkrtest", "performance",
"ggpubr", "knitr", "htmltools", "base64enc"
)
cek_paket(paket)
suppressPackageStartupMessages({
library(dplyr)
library(tidyr)
library(ggplot2)
library(afex)
library(emmeans)
library(rstatix)
library(car)
library(effectsize)
library(lme4)
library(lmerTest)
library(pbkrtest)
library(performance)
library(ggpubr)
library(knitr)
library(htmltools)
library(base64enc)
})
opsi_lama <- options(contrasts = c("contr.sum", "contr.poly"))
on.exit(options(opsi_lama), add = TRUE)
script_dir <- tryCatch(get_script_dir(), error = function(e) getwd())
kandidat <- unique(c(
file.path(script_dir, FILE_DATA),
file.path(getwd(), FILE_DATA),
normalizePath(FILE_DATA, winslash = "/", mustWork = FALSE)
))
kandidat <- kandidat[file.exists(kandidat)]
if (!length(kandidat)) {
stop(
"Berkas data tidak ditemukan.\n",
"Nama file yang dicari: ", FILE_DATA, "\n",
"Letakkan file CSV di folder script atau folder kerja RStudio."
)
}
path_data <- normalizePath(kandidat[1], winslash = "/", mustWork = TRUE)
folder <- file.path(dirname(path_data), FOLDER_HASIL)
dir.create(folder, recursive = TRUE, showWarnings = FALSE)
folder <- normalizePath(folder, winslash = "/", mustWork = TRUE)
message("Data: ", path_data)
message("Hasil: ", folder)
# ---------- pembaca laporan ----------
isi <- character(0)
status <- data.frame()
tambah <- function(html) isi <<- c(isi, html)
escape <- function(x) htmltools::htmlEscape(paste(x, collapse = "\n"))
narasi <- function(x) tambah(paste0("<p>", escape(x), "</p>"))
output <- function(x) {
teks <- capture.output(print(x))
cat(paste(teks, collapse = "\n"), "\n")
tambah(paste0("<pre>", escape(teks), "</pre>"))
invisible(x)
}
tabel <- function(x, nama) {
x <- as.data.frame(x)
write.csv(x, file.path(folder, paste0(nama, ".csv")),
row.names = FALSE, na = "", fileEncoding = "UTF-8")
if (nrow(x) > 0L) {
tambah(paste0(
"<div class='table'>",
as.character(knitr::kable(x, format = "html", digits = 4)),
"</div>"
))
} else {
narasi("Tidak ada baris untuk tabel ini.")
}
print(x)
invisible(x)
}
gambar <- function(p, nama, lebar = 10, tinggi = 6) {
path <- file.path(folder, paste0(nama, ".png"))
ggplot2::ggsave(path, plot = p, width = lebar, height = tinggi, dpi = 180)
if (TAMPILKAN_GRAFIK_RSTUDIO) {
tryCatch(print(p), error = function(e) message("Plot gagal ditampilkan: ", conditionMessage(e)))
}
tambah(paste0(
"<figure><img src='", base64enc::dataURI(file = path, mime = "image/png"),
"' alt='", escape(nama), "'><figcaption>", escape(nama), "</figcaption></figure>"
))
message("Grafik tersimpan: ", path)
}
bagian <- function(judul, f) {
message("\n>>> ", judul)
tambah(paste0("<h2>", escape(judul), "</h2>"))
warnings <- character(0)
ok <- tryCatch(
withCallingHandlers({
f()
TRUE
}, warning = function(w) {
warnings <<- c(warnings, conditionMessage(w))
invokeRestart("muffleWarning")
}),
error = function(e) {
narasi(paste("BAGIAN GAGAL:", conditionMessage(e)))
message("Bagian gagal: ", conditionMessage(e))
FALSE
}
)
if (length(warnings)) {
narasi(paste("Peringatan estimasi:", paste(unique(warnings), collapse = "; ")))
}
status <<- rbind(
status,
data.frame(
bagian = judul,
status = if (ok) "Selesai" else "Gagal",
peringatan = paste(unique(warnings), collapse = "; "),
stringsAsFactors = FALSE
)
)
invisible(ok)
}
# ---------- 1. membaca data ----------
raw <- tryCatch(
read.csv(path_data, sep = ";", dec = ".", stringsAsFactors = FALSE,
check.names = FALSE, na.strings = c("", "NA", "NaN")),
error = function(e) stop("Gagal membaca CSV: ", conditionMessage(e))
)
names(raw) <- trimws(names(raw))
wajib <- c("id", "kelompok", "usia", "waktu", "Hb")
if (!all(wajib %in% names(raw))) {
stop("Kolom tidak ditemukan: ", paste(setdiff(wajib, names(raw)), collapse = ", "))
}
level_kelompok <- c("Kontrol", "Pemberian TTD", "Pemberian TTD + ANC")
level_waktu <- c("TM0", "TM1", "TM2", "TM3")
raw <- raw |>
mutate(
id = trimws(as.character(id)),
kelompok = trimws(as.character(kelompok)),
waktu = trimws(as.character(waktu)),
usia = suppressWarnings(as.numeric(usia)),
Hb = suppressWarnings(as.numeric(Hb))
)
if (anyNA(raw$id) || any(raw$id == "")) stop("Terdapat id kosong.")
if (anyNA(raw$kelompok) || any(raw$kelompok == "")) stop("Terdapat kelompok kosong.")
if (anyNA(raw$waktu) || any(raw$waktu == "")) stop("Terdapat waktu kosong.")
if (!all(raw$kelompok %in% level_kelompok)) {
stop("Label kelompok tidak dikenali: ",
paste(setdiff(unique(raw$kelompok), level_kelompok), collapse = ", "))
}
if (!all(raw$waktu %in% level_waktu)) {
stop("Label waktu tidak dikenali: ",
paste(setdiff(unique(raw$waktu), level_waktu), collapse = ", "))
}
if (any(!is.finite(raw$Hb) & !is.na(raw$Hb))) stop("Hb memiliki nilai tak hingga.")
if (any(!is.finite(raw$usia) & !is.na(raw$usia))) stop("Usia memiliki nilai tak hingga.")
if (anyDuplicated(raw[c("id", "waktu")])) {
stop("Terdapat duplikasi kombinasi id-waktu.")
}
if (any(tapply(raw$kelompok, raw$id, function(x) length(unique(x))) != 1L)) {
stop("Satu id memiliki lebih dari satu kelompok.")
}
dat_long <- raw |>
mutate(
kelompok = factor(kelompok, levels = level_kelompok),
waktu = factor(waktu, levels = level_waktu),
waktu_num = as.integer(waktu) - 1L
) |>
arrange(id, waktu)
dat_wide <- dat_long |>
select(id, kelompok, usia, waktu, Hb) |>
pivot_wider(names_from = waktu, values_from = Hb)
hb_cols <- level_waktu
complete_id <- complete.cases(dat_wide[, hb_cols])
wide_cc <- dat_wide[complete_id, , drop = FALSE]
long_cc <- dat_long |>
semi_join(wide_cc |> select(id), by = "id")
long_obs <- dat_long |>
filter(!is.na(Hb))
if (n_distinct(wide_cc$id) < 6L) stop("Peserta lengkap terlalu sedikit untuk analisis berulang.")
if (n_distinct(long_cc$id) < 6L) stop("Peserta lengkap terlalu sedikit untuk analisis berulang.")
if (any(table(dat_long$kelompok) < 3L)) stop("Setiap kelompok sebaiknya memiliki cukup observasi.")
write.csv(dat_wide, file.path(folder, "data_wide.csv"), row.names = FALSE, na = "")
write.csv(dat_long, file.path(folder, "data_long.csv"), row.names = FALSE, na = "")
write.csv(wide_cc, file.path(folder, "data_complete_case.csv"), row.names = FALSE, na = "")
# ---------- 2. deskriptif ----------
bagian("1. Sumber dan kelengkapan data", function() {
narasi(paste(
"Data hemoglobin anemia dianalisis dalam format long dengan variabel id, kelompok, usia, waktu, dan Hb.",
"Model utama menggunakan 3 kelompok dan 4 waktu pengukuran (TM0–TM3)."
))
narasi(paste(
n_distinct(dat_long$id), "subjek;",
nrow(dat_long), "baris observasi;",
nrow(wide_cc), "subjek lengkap untuk ANOVA;"
))
tabel(dat_long |>
group_by(kelompok, waktu) |>
summarise(
n_total = n(),
n_tersedia = sum(!is.na(Hb)),
n_hilang = sum(is.na(Hb)),
.groups = "drop"
),
"01_kelengkapan")
tabel(dat_wide |>
group_by(kelompok) |>
summarise(
n_total = n(),
n_lengkap = sum(complete_id),
n_tidak_lengkap = sum(!complete_id),
.groups = "drop"
),
"01_peserta")
narasi("ANOVA memakai peserta yang memiliki Hb lengkap pada seluruh waktu. LMM memakai seluruh pengukuran Hb yang tersedia.")
})
bagian("2. Statistik deskriptif dan visualisasi", function() {
desk <- function(d) {
d |>
group_by(kelompok, waktu) |>
summarise(ci_mean(Hb), .groups = "drop")
}
tabel(desk(dat_long), "02_deskriptif_semua_tersedia")
tabel(desk(long_cc), "02_deskriptif_complete_case")
gambar(
ggplot(dat_long, aes(waktu, Hb, colour = kelompok, group = kelompok)) +
stat_summary(fun = mean, geom = "line", linewidth = 1) +
stat_summary(fun = mean, geom = "point", size = 2) +
stat_summary(fun.data = mean_cl_normal, geom = "errorbar", width = .2) +
theme_bw(base_size = 12) +
theme(legend.position = "bottom") +
labs(title = "Profil Hb: semua pengukuran tersedia", x = "Waktu", y = "Hb (g/dL)", colour = "Kelompok"),
"02_profil_hb",
10, 6
)
gambar(
ggplot(long_cc, aes(waktu, Hb, group = id)) +
geom_line(alpha = .15) +
stat_summary(aes(group = kelompok), fun = mean, geom = "line", linewidth = 1.1) +
facet_wrap(~kelompok) +
theme_bw(base_size = 12) +
labs(title = "Lintasan individu: peserta lengkap", x = "Waktu", y = "Hb (g/dL)"),
"02_lintasan",
12, 7
)
for (g in level_kelompok) {
z <- wide_cc[wide_cc$kelompok == g, hb_cols, drop = FALSE]
narasi(paste("Kovarians dan korelasi dalam kelompok:", g))
output(round(cov(z), 3))
output(round(cor(z), 3))
}
})
# ---------- 3. asumsi ----------
bagian("3. Asumsi ANOVA pada peserta lengkap", function() {
tabel(long_cc |> group_by(kelompok, waktu) |> identify_outliers(Hb), "03_outlier")
tabel(long_cc |> group_by(kelompok, waktu) |> shapiro_test(Hb), "03_shapiro")
gambar(
ggpubr::ggqqplot(long_cc, "Hb", facet.by = c("kelompok", "waktu")),
"03_qq_per_sel",
12, 9
)
tabel(long_cc |> group_by(waktu) |> levene_test(Hb ~ kelompok), "03_levene")
tabel(rstatix::box_m(wide_cc[, hb_cols], wide_cc$kelompok), "03_box_m")
narasi("p > 0,05 tidak membuktikan normalitas atau kesamaan varians. Outlier statistik dipertahankan dalam analisis utama kecuali ada alasan substantif untuk mengecualikannya.")
})
# ---------- 4. RM ANOVA satu kelompok ----------
aov1 <- NULL
aov2 <- NULL
lmm <- NULL
lmm_ri <- NULL
lmm_rs <- NULL
bagian("4. RM ANOVA satu kelompok", function() {
if (!(KELOMPOK_FOKUS %in% level_kelompok)) {
stop("KELOMPOK_FOKUS tidak dikenali.")
}
d1 <- long_cc |>
filter(kelompok == KELOMPOK_FOKUS)
if (n_distinct(d1$id) < 4L) stop("Jumlah peserta lengkap pada kelompok fokus terlalu sedikit.")
narasi(paste("Kelompok fokus:", KELOMPOK_FOKUS, "—", n_distinct(d1$id), "peserta lengkap."))
gambar(
ggpubr::ggqqplot(d1, "Hb", facet.by = "waktu") +
labs(title = paste("Q-Q Hb per waktu:", KELOMPOK_FOKUS)),
"04_qq_kelompok_fokus",
10, 6
)
output(rstatix::anova_test(data = d1, dv = Hb, wid = id, within = waktu, effect.size = "pes"))
aov1 <<- afex::aov_ez(
id = "id",
dv = "Hb",
data = d1,
within = "waktu",
anova_table = list(es = c("ges", "pes"), correction = "GG")
)
output(aov1)
output(summary(aov1))
output(aov1$Anova)
tabel(as.data.frame(aov1$anova_table) |> tibble::rownames_to_column("efek"), "04_anova_gg")
output(effectsize::eta_squared(aov1, partial = TRUE))
p <- as.numeric(aov1$anova_table[1, "Pr(>F)"])
narasi(paste0("Efek waktu dengan koreksi GG: p ", fp(p), "."))
})
bagian("5. Post hoc satu kelompok dan tren waktu", function() {
if (is.null(aov1)) stop("Model RM ANOVA belum tersedia.")
em <- emmeans::emmeans(aov1, ~ waktu, model = "multivariate")
tabel(summary(em), "05_emmeans")
tabel(summary(pairs(em, adjust = "bonferroni"), infer = c(TRUE, TRUE)), "05_pasangan_bonferroni")
tabel(summary(contrast(em, "trt.vs.ctrl", ref = 1, adjust = "holm"), infer = c(TRUE, TRUE)), "05_vs_baseline_holm")
pol <- poly(0:3, degree = 3)
koef <- list(
linear = pol[, 1],
kuadratik = pol[, 2],
kubik = pol[, 3]
)
tabel(summary(contrast(em, method = koef, adjust = "holm"), infer = c(TRUE, TRUE)), "05_tren")
narasi("Tren waktu menggunakan urutan TM0–TM3. Koefisien ortogonal dinormalisasi sehingga estimate bukan kenaikan Hb per satuan waktu.")
})
# ---------- 6. nonparametrik ----------
bagian("6. Pembanding nonparametrik satu kelompok", function() {
if (is.null(aov1)) stop("RM ANOVA belum tersedia.")
d1 <- long_cc |> filter(kelompok == KELOMPOK_FOKUS)
tabel(rstatix::friedman_test(d1, Hb ~ waktu | id), "06_friedman")
tabel(rstatix::friedman_effsize(d1, Hb ~ waktu | id), "06_kendall_w")
w <- wide_cc[wide_cc$kelompok == KELOMPOK_FOKUS, ]
ij <- combn(seq_along(hb_cols), 2)
hasil <- lapply(seq_len(ncol(ij)), function(j) {
a <- ij[1, j]
b <- ij[2, j]
wt <- wilcox.test(w[[hb_cols[a]]], w[[hb_cols[b]]], paired = TRUE, exact = FALSE)
data.frame(
waktu_1 = level_waktu[a],
waktu_2 = level_waktu[b],
n_pasangan = nrow(w),
V = unname(wt$statistic),
p = wt$p.value,
stringsAsFactors = FALSE
)
}) |> bind_rows() |> mutate(p_bonferroni = p.adjust(p, "bonferroni"))
tabel(hasil, "06_wilcoxon")
})
# ---------- 7. mixed design ANOVA ----------
bagian("7. Mixed Design ANOVA kelompok × waktu", function() {
aov2 <<- afex::aov_ez(
id = "id",
dv = "Hb",
data = long_cc,
between = "kelompok",
within = "waktu",
anova_table = list(es = c("ges", "pes"), correction = "GG")
)
output(aov2)
output(summary(aov2))
output(aov2$Anova)
tabel(as.data.frame(aov2$anova_table) |> tibble::rownames_to_column("efek"), "07_anova_gg")
output(effectsize::eta_squared(aov2, partial = TRUE))
})
bagian("7b. Visualisasi interaksi kelompok dan waktu", function() {
if (is.null(aov2)) stop("Model Mixed Design ANOVA belum tersedia.")
gambar(
afex::afex_plot(aov2, x = "waktu", trace = "kelompok", error = "within",
mapping = c("colour", "shape", "linetype")) +
labs(title = "Mixed Design ANOVA: kelompok × waktu", x = "Waktu", y = "Hb (g/dL)"),
"07_interaksi_anova",
11, 7
)
})
# ---------- 8. efek sederhana ----------
bagian("8. Efek sederhana dan post hoc antarkelompok", function() {
if (is.null(aov2)) stop("Model Mixed Design ANOVA belum tersedia.")
jt1 <- as.data.frame(joint_tests(aov2, by = "kelompok", model = "multivariate"))
jt1$p_holm_antar_kelompok <- p.adjust(jt1$p.value, "holm")
tabel(jt1, "08_efek_waktu_per_kelompok")
jt2 <- as.data.frame(joint_tests(aov2, by = "waktu", model = "multivariate"))
jt2$p_holm_antar_waktu <- p.adjust(jt2$p.value, "holm")
tabel(jt2, "08_efek_kelompok_per_waktu")
ew <- emmeans(aov2, ~ waktu | kelompok, model = "multivariate")
tabel(summary(pairs(ew, adjust = "holm"), infer = c(TRUE, TRUE)), "08_pairwise_waktu_dalam_kelompok")
ek <- emmeans(aov2, ~ kelompok | waktu, model = "multivariate")
tabel(summary(pairs(ek, adjust = "tukey"), infer = c(TRUE, TRUE)), "08_kelompok_per_waktu")
})
# ---------- 9. lmm ----------
bagian("9. LMM dengan semua pengukuran tersedia", function() {
lmm_ri <<- lmerTest::lmer(
Hb ~ kelompok * waktu + (1 | id),
data = long_obs,
REML = TRUE,
control = lmerControl(optimizer = "bobyqa")
)
lmm_rs <<- tryCatch(
lmerTest::lmer(
Hb ~ kelompok * waktu + (1 + waktu_num | id),
data = long_obs,
REML = TRUE,
control = lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 200000))
),
error = function(e) {
narasi(paste("Random slope gagal diestimasi; memakai random intercept:", conditionMessage(e)))
NULL
}
)
info_model <- function(m, nama) {
data.frame(
model = nama,
n_observasi = nobs(m),
AIC = AIC(m),
BIC = BIC(m),
singular = lme4::isSingular(m),
konvergensi = paste(m@optinfo$conv$lme4$messages, collapse = "; "),
stringsAsFactors = FALSE
)
}
info_rs <- if (!is.null(lmm_rs)) info_model(lmm_rs, "random_intercept_slope") else NULL
tabel(bind_rows(info_model(lmm_ri, "random_intercept"), info_rs), "09_perbandingan_model")
layak <- !is.null(lmm_rs) && !isSingular(lmm_rs) && is.null(lmm_rs@optinfo$conv$lme4$messages)
pakai_rs <- layak && AIC(lmm_rs) < AIC(lmm_ri)
lmm <<- if (pakai_rs) lmm_rs else lmm_ri
narasi(paste("Model yang dipakai:", if (pakai_rs) "random intercept + slope waktu." else "random intercept."))
output(summary(lmm))
output(VarCorr(lmm))
hasil <- anova(lmm, type = 3, ddf = "Kenward-Roger")
tabel(as.data.frame(hasil) |> tibble::rownames_to_column("efek"), "09_lmm_kr")
output(performance::icc(lmm_ri))
})
bagian("10. Diagnostik LMM", function() {
if (is.null(lmm)) stop("LMM belum tersedia.")
diag <- data.frame(
fitted = fitted(lmm),
residual = resid(lmm),
kelompok = long_obs$kelompok,
waktu = long_obs$waktu
)
gambar(
ggplot(diag, aes(sample = residual)) + stat_qq() + stat_qq_line() + theme_bw() +
labs(title = "Q-Q residual LMM"),
"10_qq_residual",
8, 6
)
gambar(
ggplot(diag, aes(fitted, residual, colour = kelompok)) +
geom_point(alpha = .35) +
geom_hline(yintercept = 0, linetype = 2) +
theme_bw() +
labs(x = "Prediksi", y = "Residual", title = "Residual terhadap prediksi"),
"10_residual_prediksi",
8, 6
)
gambar(
ggplot(diag, aes(waktu, residual, fill = kelompok)) +
geom_boxplot() + theme_bw() +
labs(title = "Residual menurut kelompok dan waktu"),
"10_residual_sel",
10, 6
)
output(performance::check_singularity(lmm))
output(performance::check_convergence(lmm))
})
bagian("11. Informasi sesi dan batas interpretasi", function() {
narasi("Taraf signifikansi ditetapkan pada α = 0,05. Interpretasi mempertimbangkan nilai p, ukuran efek, interval kepercayaan, dan arah perubahan.")
output(sessionInfo())
})
# ---------- simpan laporan ----------
tambah("<h2>Status setiap bagian</h2>")
tabel(status, "status_analisis")
css <- "body{font:16px/1.6 Arial,sans-serif;max-width:1100px;margin:40px auto;padding:0 24px;color:#18332e}h1,h2{color:#0b6b4f}h2{border-top:1px solid #d9e4e0;padding-top:24px}pre{background:#f0f5f3;padding:16px;overflow:auto;font-size:13px;color:#182822}.table{overflow:auto}table{border-collapse:collapse;font-size:13px;width:100%}td,th{border:1px solid #d9e4e0;padding:8px;text-align:left}th{background:#e7f2ee}img{max-width:100%}summary{cursor:pointer;font-weight:bold}"
selesai <- sum(status$status == "Selesai", na.rm = TRUE)
header <- paste0(
"<!doctype html><html lang='id'><head><meta charset='UTF-8'>",
"<meta name='viewport' content='width=device-width,initial-scale=1'>",
"<title>Analisis Hb — pengukuran berulang</title><style>", css, "</style></head><body>",
"<h1>Analisis Pengukuran Berulang Hemoglobin</h1>",
"<table class='identitas'><tbody>",
"<tr><th>File data</th><td>", escape(FILE_DATA), "</td></tr>",
"<tr><th>Kelompok fokus</th><td>", escape(KELOMPOK_FOKUS), "</td></tr>",
"<tr><th>Waktu</th><td>TM0, TM1, TM2, TM3</td></tr>",
"<tr><th>Subjek</th><td>", n_distinct(dat_long$id), "</td></tr>",
"</tbody></table>",
"<p>Dibuat: ", escape(format(Sys.time())), " · Bagian selesai: ", selesai, "/", nrow(status), "</p>"
)
path_html <- file.path(folder, "laporan_analisis_hb.html")
writeLines(c(header, isi, "</body></html>"), path_html, useBytes = TRUE)
saveRDS(
list(
data_wide = dat_wide,
data_long = dat_long,
aov_satu = aov1,
aov_campuran = aov2,
lmm = lmm,
status = status
),
file.path(folder, "objek_analisis.rds")
)
writeLines(capture.output(sessionInfo()), file.path(folder, "sessionInfo.txt"))
message("\nLaporan tersedia: ", path_html)
message("Durasi: ", round(as.numeric(difftime(Sys.time(), waktu_mulai, units = "secs")), 1), " detik.")
if (any(status$status == "Gagal")) {
message("Terdapat bagian analisis yang gagal; rinciannya tercatat dalam status_analisis.csv dan laporan HTML.")
}
if (BUKA_HTML_OTOMATIS && interactive()) {
try(utils::browseURL(path_html), silent = TRUE)
}
invisible(list(folder = folder, status = status))
}
# ============================ EKSEKUSI ================================
hasil_analisis <- jalankan_analisis()
## Registered S3 method overwritten by 'lme4':
## method from
## na.action.merMod car
## Data: D:/2026/S2 UNMUL/TUGAS/BIOSTAT/data_hemoglobin_anemia_long.csv
## Hasil: D:/2026/S2 UNMUL/TUGAS/BIOSTAT/hasil_analisis_hb
##
## >>> 1. Sumber dan kelengkapan data
## kelompok waktu n_total n_tersedia n_hilang
## 1 Kontrol TM0 30 30 0
## 2 Kontrol TM1 30 30 0
## 3 Kontrol TM2 30 30 0
## 4 Kontrol TM3 30 30 0
## 5 Pemberian TTD TM0 30 30 0
## 6 Pemberian TTD TM1 30 30 0
## 7 Pemberian TTD TM2 30 30 0
## 8 Pemberian TTD TM3 30 30 0
## 9 Pemberian TTD + ANC TM0 30 30 0
## 10 Pemberian TTD + ANC TM1 30 30 0
## 11 Pemberian TTD + ANC TM2 30 30 0
## 12 Pemberian TTD + ANC TM3 30 30 0
## kelompok n_total n_lengkap n_tidak_lengkap
## 1 Kontrol 30 90 0
## 2 Pemberian TTD 30 90 0
## 3 Pemberian TTD + ANC 30 90 0
##
## >>> 2. Statistik deskriptif dan visualisasi
## kelompok waktu n mean sd median min max se
## 1 Kontrol TM0 30 8.736667 0.5301160 8.70 8.0 9.8 0.09678550
## 2 Kontrol TM1 30 8.773333 0.5362278 8.65 7.9 9.9 0.09790135
## 3 Kontrol TM2 30 8.840000 0.5468405 8.85 8.0 10.0 0.09983895
## 4 Kontrol TM3 30 8.870000 0.5831839 8.80 7.9 10.1 0.10647432
## 5 Pemberian TTD TM0 30 8.763333 0.5792286 8.80 7.5 9.8 0.10575219
## 6 Pemberian TTD TM1 30 9.136667 0.6189442 9.15 7.9 10.2 0.11300324
## 7 Pemberian TTD TM2 30 9.503333 0.6122223 9.55 8.0 10.4 0.11177598
## 8 Pemberian TTD TM3 30 9.963333 0.6702976 9.95 8.6 10.9 0.12237904
## 9 Pemberian TTD + ANC TM0 30 8.780000 0.6509410 8.85 7.5 9.8 0.11884502
## 10 Pemberian TTD + ANC TM1 30 9.310000 0.6849868 9.35 8.0 10.3 0.12506090
## 11 Pemberian TTD + ANC TM2 30 9.930000 0.7066921 9.85 8.7 10.9 0.12902374
## 12 Pemberian TTD + ANC TM3 30 10.250000 0.5764038 10.20 9.3 10.9 0.10523646
## lower_ci upper_ci
## 1 8.538718 8.934615
## 2 8.573103 8.973564
## 3 8.635806 9.044194
## 4 8.652236 9.087764
## 5 8.547046 8.979621
## 6 8.905549 9.367784
## 7 9.274726 9.731941
## 8 9.713040 10.213627
## 9 8.536935 9.023065
## 10 9.054222 9.565778
## 11 9.666117 10.193883
## 12 10.034767 10.465233
## kelompok waktu n mean sd median min max se
## 1 Kontrol TM0 30 8.736667 0.5301160 8.70 8.0 9.8 0.09678550
## 2 Kontrol TM1 30 8.773333 0.5362278 8.65 7.9 9.9 0.09790135
## 3 Kontrol TM2 30 8.840000 0.5468405 8.85 8.0 10.0 0.09983895
## 4 Kontrol TM3 30 8.870000 0.5831839 8.80 7.9 10.1 0.10647432
## 5 Pemberian TTD TM0 30 8.763333 0.5792286 8.80 7.5 9.8 0.10575219
## 6 Pemberian TTD TM1 30 9.136667 0.6189442 9.15 7.9 10.2 0.11300324
## 7 Pemberian TTD TM2 30 9.503333 0.6122223 9.55 8.0 10.4 0.11177598
## 8 Pemberian TTD TM3 30 9.963333 0.6702976 9.95 8.6 10.9 0.12237904
## 9 Pemberian TTD + ANC TM0 30 8.780000 0.6509410 8.85 7.5 9.8 0.11884502
## 10 Pemberian TTD + ANC TM1 30 9.310000 0.6849868 9.35 8.0 10.3 0.12506090
## 11 Pemberian TTD + ANC TM2 30 9.930000 0.7066921 9.85 8.7 10.9 0.12902374
## 12 Pemberian TTD + ANC TM3 30 10.250000 0.5764038 10.20 9.3 10.9 0.10523646
## lower_ci upper_ci
## 1 8.538718 8.934615
## 2 8.573103 8.973564
## 3 8.635806 9.044194
## 4 8.652236 9.087764
## 5 8.547046 8.979621
## 6 8.905549 9.367784
## 7 9.274726 9.731941
## 8 9.713040 10.213627
## 9 8.536935 9.023065
## 10 9.054222 9.565778
## 11 9.666117 10.193883
## 12 10.034767 10.465233

## Grafik tersimpan: D:/2026/S2 UNMUL/TUGAS/BIOSTAT/hasil_analisis_hb/02_profil_hb.png

## Grafik tersimpan: D:/2026/S2 UNMUL/TUGAS/BIOSTAT/hasil_analisis_hb/02_lintasan.png
## TM0 TM1 TM2 TM3
## TM0 0.281 0.276 0.277 0.299
## TM1 0.276 0.288 0.273 0.290
## TM2 0.277 0.273 0.299 0.308
## TM3 0.299 0.290 0.308 0.340
## TM0 TM1 TM2 TM3
## TM0 1.000 0.970 0.956 0.967
## TM1 0.970 1.000 0.930 0.926
## TM2 0.956 0.930 1.000 0.966
## TM3 0.967 0.926 0.966 1.000
## TM0 TM1 TM2 TM3
## TM0 0.336 0.340 0.339 0.352
## TM1 0.340 0.383 0.345 0.359
## TM2 0.339 0.345 0.375 0.348
## TM3 0.352 0.359 0.348 0.449
## TM0 TM1 TM2 TM3
## TM0 1.000 0.948 0.957 0.908
## TM1 0.948 1.000 0.911 0.864
## TM2 0.957 0.911 1.000 0.848
## TM3 0.908 0.864 0.848 1.000
## TM0 TM1 TM2 TM3
## TM0 0.424 0.430 0.437 0.350
## TM1 0.430 0.469 0.452 0.365
## TM2 0.437 0.452 0.499 0.378
## TM3 0.350 0.365 0.378 0.332
## TM0 TM1 TM2 TM3
## TM0 1.000 0.965 0.950 0.934
## TM1 0.965 1.000 0.934 0.924
## TM2 0.950 0.934 1.000 0.927
## TM3 0.934 0.924 0.927 1.000
##
## >>> 3. Asumsi ANOVA pada peserta lengkap
## kelompok waktu id usia Hb waktu_num is.outlier is.extreme
## 1 Kontrol TM0 P007 24 9.8 0 TRUE FALSE
## 2 Kontrol TM0 P022 29 9.8 0 TRUE FALSE
## 3 Kontrol TM3 P007 24 10.1 3 TRUE FALSE
## 4 Pemberian TTD TM2 P045 39 8.0 2 TRUE FALSE
## 5 Pemberian TTD TM2 P048 30 8.1 2 TRUE FALSE
## kelompok waktu variable statistic p
## 1 Kontrol TM0 Hb 0.9256333 0.037641323
## 2 Kontrol TM1 Hb 0.9425960 0.106856847
## 3 Kontrol TM2 Hb 0.9572106 0.262429244
## 4 Kontrol TM3 Hb 0.9503149 0.172375376
## 5 Pemberian TTD TM0 Hb 0.9720809 0.597542969
## 6 Pemberian TTD TM1 Hb 0.9609214 0.326967390
## 7 Pemberian TTD TM2 Hb 0.9457828 0.130226887
## 8 Pemberian TTD TM3 Hb 0.9534881 0.209441459
## 9 Pemberian TTD + ANC TM0 Hb 0.9586031 0.285198854
## 10 Pemberian TTD + ANC TM1 Hb 0.9516830 0.187515319
## 11 Pemberian TTD + ANC TM2 Hb 0.9281162 0.043769627
## 12 Pemberian TTD + ANC TM3 Hb 0.8668000 0.001423043

## Grafik tersimpan: D:/2026/S2 UNMUL/TUGAS/BIOSTAT/hasil_analisis_hb/03_qq_per_sel.png
## waktu df1 df2 statistic p
## 1 TM0 2 87 1.1781739 0.3127031
## 2 TM1 2 87 1.7669237 0.1769335
## 3 TM2 2 87 2.0384721 0.1364017
## 4 TM3 2 87 0.8676822 0.4235254
## statistic p.value parameter
## 1 43.56665 0.00171942 20
## method
## 1 Box's M-test for Homogeneity of Covariance Matrices
##
## >>> 4. RM ANOVA satu kelompok

## Grafik tersimpan: D:/2026/S2 UNMUL/TUGAS/BIOSTAT/hasil_analisis_hb/04_qq_kelompok_fokus.png
## ANOVA Table (type III tests)
##
## $ANOVA
## Effect DFn DFd F p p<.05 pes
## 1 waktu 3 87 441.902 1.6e-52 * 0.938
##
## $`Mauchly's Test for Sphericity`
## Effect W p p<.05
## 1 waktu 0.776 0.219
##
## $`Sphericity Corrections`
## Effect GGe DF[GG] p[GG] p[GG]<.05 HFe DF[HF] p[HF]
## 1 waktu 0.884 2.65, 76.86 1.08e-46 * 0.981 2.94, 85.31 1.49e-51
## p[HF]<.05
## 1 *
##
## Anova Table (Type 3 tests)
##
## Response: Hb
## Effect df MSE F ges pes p.value
## 1 waktu 2.65, 76.86 0.03 441.90 *** .435 .938 <.001
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1
##
## Sphericity correction method: GG
##
## Univariate Type III Repeated-Measures ANOVA Assuming Sphericity
##
## Sum Sq num Df Error SS den Df F value Pr(>F)
## (Intercept) 10984.4 1 47.486 29 6708.3 < 2.2e-16 ***
## waktu 38.5 3 2.527 87 441.9 < 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.77597 0.21857
##
##
## Greenhouse-Geisser and Huynh-Feldt Corrections
## for Departure from Sphericity
##
## GG eps Pr(>F[GG])
## waktu 0.8835 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## HF eps Pr(>F[HF])
## waktu 0.9806045 1.49376e-51
##
## Type III Repeated Measures MANOVA Tests: Pillai test statistic
## Df test stat approx F num Df den Df Pr(>F)
## (Intercept) 1 0.99570 6708.3 1 29 < 2.2e-16 ***
## waktu 1 0.98236 501.3 3 27 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## efek num Df den Df MSE F pes ges Pr(>F)
## 1 waktu 2.65051 76.86478 0.03287917 441.9022 0.9384161 0.4350298 1.081739e-46
## # Effect Size for ANOVA (Type III)
##
## Parameter | Eta2 (partial) | 95% CI
## -----------------------------------------
## waktu | 0.94 | [0.92, 1.00]
##
## - One-sided CIs: upper bound fixed at [1.00].
##
## >>> 5. Post hoc satu kelompok dan tren waktu
## waktu emmean SE df lower.CL upper.CL
## TM0 8.78 0.1188450 29 8.536935 9.023065
## TM1 9.31 0.1250609 29 9.054222 9.565778
## TM2 9.93 0.1290237 29 9.666117 10.193883
## TM3 10.25 0.1052365 29 10.034767 10.465233
##
## Confidence level used: 0.95
## contrast estimate SE df lower.CL upper.CL t.ratio p.value
## TM0 - TM1 -0.53 0.03292276 29 -0.6232225 -0.4367775 -16.098 <0.0001
## TM0 - TM2 -1.15 0.04032911 29 -1.2641940 -1.0358060 -28.515 <0.0001
## TM0 - TM3 -1.47 0.04292469 29 -1.5915435 -1.3484565 -34.246 <0.0001
## TM1 - TM2 -0.62 0.04633710 29 -0.7512059 -0.4887941 -13.380 <0.0001
## TM1 - TM3 -0.94 0.04880173 29 -1.0781847 -0.8018153 -19.262 <0.0001
## TM2 - TM3 -0.32 0.05037788 29 -0.4626476 -0.1773524 -6.352 <0.0001
##
## Confidence level used: 0.95
## Conf-level adjustment: bonferroni method for 6 estimates
## P value adjustment: bonferroni method for 6 tests
## contrast estimate SE df lower.CL upper.CL t.ratio p.value
## TM1 - TM0 0.53 0.03292276 29 0.4463463 0.6136537 16.098 <0.0001
## TM2 - TM0 1.15 0.04032911 29 1.0475274 1.2524726 28.515 <0.0001
## TM3 - TM0 1.47 0.04292469 29 1.3609323 1.5790677 34.246 <0.0001
##
## Confidence level used: 0.95
## Conf-level adjustment: bonferroni method for 3 estimates
## P value adjustment: holm method for 3 tests
## contrast estimate SE df lower.CL upper.CL t.ratio p.value
## linear 1.1247422 0.03153451 29 1.0446159 1.2048685 35.667 <0.0001
## kuadratik -0.1050000 0.03016716 29 -0.1816520 -0.0283480 -3.481 0.0032
## kubik -0.0872067 0.03162914 29 -0.1675734 -0.0068399 -2.757 0.0100
##
## Confidence level used: 0.95
## Conf-level adjustment: bonferroni method for 3 estimates
## P value adjustment: holm method for 3 tests
##
## >>> 6. Pembanding nonparametrik satu kelompok
## .y. n statistic df p method
## 1 Hb 30 86.41611 3 1.288722e-18 Friedman test
## .y. n effsize method magnitude
## 1 Hb 30 0.960179 Kendall W large
## waktu_1 waktu_2 n_pasangan V p p_bonferroni
## 1 TM0 TM1 30 0.0 1.735764e-06 1.041458e-05
## 2 TM0 TM2 30 0.0 1.781217e-06 1.068730e-05
## 3 TM0 TM3 30 0.0 1.758922e-06 1.055353e-05
## 4 TM1 TM2 30 0.0 1.734667e-06 1.040800e-05
## 5 TM1 TM3 30 0.0 1.780097e-06 1.068058e-05
## 6 TM2 TM3 30 8.5 9.781069e-06 5.868641e-05
##
## >>> 7. Mixed Design ANOVA kelompok × waktu
## Anova Table (Type 3 tests)
##
## Response: Hb
## Effect df MSE F ges pes p.value
## 1 kelompok 2, 87 1.41 13.06 *** .221 .231 <.001
## 2 waktu 2.44, 212.67 0.03 545.71 *** .257 .862 <.001
## 3 kelompok:waktu 4.89, 212.67 0.03 107.20 *** .120 .711 <.001
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1
##
## Sphericity correction method: GG
##
## Univariate Type III Repeated-Measures ANOVA Assuming Sphericity
##
## Sum Sq num Df Error SS den Df F value Pr(>F)
## (Intercept) 30723.0 1 122.619 87 21798.351 < 2.2e-16 ***
## kelompok 36.8 2 122.619 87 13.061 1.096e-05 ***
## waktu 44.9 3 7.156 261 545.705 < 2.2e-16 ***
## kelompok:waktu 17.6 6 7.156 261 107.198 < 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.64119 3.6178e-07
## kelompok:waktu 0.64119 3.6178e-07
##
##
## Greenhouse-Geisser and Huynh-Feldt Corrections
## for Departure from Sphericity
##
## GG eps Pr(>F[GG])
## waktu 0.81483 < 2.2e-16 ***
## kelompok:waktu 0.81483 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## HF eps Pr(>F[HF])
## waktu 0.8401417 1.216338e-94
## kelompok:waktu 0.8401417 3.923773e-57
##
## Type III Repeated Measures MANOVA Tests: Pillai test statistic
## Df test stat approx F num Df den Df Pr(>F)
## (Intercept) 1 0.99602 21798.4 1 87 < 2.2e-16 ***
## kelompok 2 0.23092 13.1 2 87 1.096e-05 ***
## waktu 1 0.96567 797.1 3 85 < 2.2e-16 ***
## kelompok:waktu 2 1.04668 31.5 6 172 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## efek num Df den Df MSE F pes ges
## 1 kelompok 2.000000 87.0000 1.40941858 13.06096 0.2309183 0.2209997
## 2 waktu 2.444498 212.6713 0.03364621 545.70504 0.8624952 0.2569773
## 3 kelompok:waktu 4.888996 212.6713 0.03364621 107.19838 0.7113439 0.1196247
## Pr(>F)
## 1 1.095980e-05
## 2 7.064013e-92
## 3 1.720301e-55
## # Effect Size for ANOVA (Type III)
##
## Parameter | Eta2 (partial) | 95% CI
## ----------------------------------------------
## kelompok | 0.23 | [0.11, 1.00]
## waktu | 0.86 | [0.84, 1.00]
## kelompok:waktu | 0.71 | [0.67, 1.00]
##
## - One-sided CIs: upper bound fixed at [1.00].
##
## >>> 7b. Visualisasi interaksi kelompok dan waktu

## Grafik tersimpan: D:/2026/S2 UNMUL/TUGAS/BIOSTAT/hasil_analisis_hb/07_interaksi_anova.png
##
## >>> 8. Efek sederhana dan post hoc antarkelompok
## model term kelompok df1 df2 F.ratio p.value
## 1 waktu Kontrol 3 87 5.776 1.194158e-03
## 4 waktu Pemberian TTD 3 87 402.108 7.421211e-51
## 7 waktu Pemberian TTD + ANC 3 87 735.742 1.118461e-61
## p_holm_antar_kelompok
## 1 1.194158e-03
## 4 1.484242e-50
## 7 3.355382e-61
## model term waktu df1 df2 F.ratio p.value p_holm_antar_waktu
## 1 kelompok TM0 2 87 0.041 9.595254e-01 9.595254e-01
## 3 kelompok TM1 2 87 5.923 3.876646e-03 7.753292e-03
## 5 kelompok TM2 2 87 23.143 8.731459e-09 2.619438e-08
## 7 kelompok TM3 2 87 42.553 1.294062e-13 5.176249e-13
## kelompok = Kontrol:
## contrast estimate SE df lower.CL upper.CL t.ratio p.value
## TM0 - TM1 -0.0366667 0.03126535 87 -0.1210807 0.0477474 -1.173 0.4882
## TM0 - TM2 -0.1033333 0.03433365 87 -0.1960315 -0.0106351 -3.010 0.0171
## TM0 - TM3 -0.1333333 0.04193439 87 -0.2465530 -0.0201137 -3.180 0.0123
## TM1 - TM2 -0.0666667 0.04377465 87 -0.1848548 0.0515215 -1.523 0.3942
## TM1 - TM3 -0.0966667 0.05111902 87 -0.2346841 0.0413508 -1.891 0.2478
## TM2 - TM3 -0.0300000 0.05022173 87 -0.1655948 0.1055948 -0.597 0.5518
##
## kelompok = Pemberian TTD:
## contrast estimate SE df lower.CL upper.CL t.ratio p.value
## TM0 - TM1 -0.3733333 0.03126535 87 -0.4577474 -0.2889193 -11.941 <0.0001
## TM0 - TM2 -0.7400000 0.03433365 87 -0.8326982 -0.6473018 -21.553 <0.0001
## TM0 - TM3 -1.2000000 0.04193439 87 -1.3132196 -1.0867804 -28.616 <0.0001
## TM1 - TM2 -0.3666667 0.04377465 87 -0.4848548 -0.2484785 -8.376 <0.0001
## TM1 - TM3 -0.8266667 0.05111902 87 -0.9646841 -0.6886492 -16.171 <0.0001
## TM2 - TM3 -0.4600000 0.05022173 87 -0.5955948 -0.3244052 -9.159 <0.0001
##
## kelompok = Pemberian TTD + ANC:
## contrast estimate SE df lower.CL upper.CL t.ratio p.value
## TM0 - TM1 -0.5300000 0.03126535 87 -0.6144140 -0.4455860 -16.952 <0.0001
## TM0 - TM2 -1.1500000 0.03433365 87 -1.2426982 -1.0573018 -33.495 <0.0001
## TM0 - TM3 -1.4700000 0.04193439 87 -1.5832196 -1.3567804 -35.055 <0.0001
## TM1 - TM2 -0.6200000 0.04377465 87 -0.7381882 -0.5018118 -14.163 <0.0001
## TM1 - TM3 -0.9400000 0.05111902 87 -1.0780174 -0.8019826 -18.388 <0.0001
## TM2 - TM3 -0.3200000 0.05022173 87 -0.4555948 -0.1844052 -6.372 <0.0001
##
## Confidence level used: 0.95
## Conf-level adjustment: bonferroni method for 6 estimates
## P value adjustment: holm method for 6 tests
## waktu = TM0:
## contrast estimate SE df lower.CL
## Kontrol - Pemberian TTD -0.0266667 0.1520419 87 -0.3892074
## Kontrol - (Pemberian TTD + ANC) -0.0433333 0.1520419 87 -0.4058741
## Pemberian TTD - (Pemberian TTD + ANC) -0.0166667 0.1520419 87 -0.3792074
## upper.CL t.ratio p.value
## 0.3358741 -0.175 0.9832
## 0.3192074 -0.285 0.9562
## 0.3458741 -0.110 0.9934
##
## waktu = TM1:
## contrast estimate SE df lower.CL
## Kontrol - Pemberian TTD -0.3633333 0.1591532 87 -0.7428310
## Kontrol - (Pemberian TTD + ANC) -0.5366667 0.1591532 87 -0.9161643
## Pemberian TTD - (Pemberian TTD + ANC) -0.1733333 0.1591532 87 -0.5528310
## upper.CL t.ratio p.value
## 0.0161643 -2.283 0.0636
## -0.1571690 -3.372 0.0032
## 0.2061643 -1.089 0.5234
##
## waktu = TM2:
## contrast estimate SE df lower.CL
## Kontrol - Pemberian TTD -0.6633333 0.1614699 87 -1.0483551
## Kontrol - (Pemberian TTD + ANC) -1.0900000 0.1614699 87 -1.4750218
## Pemberian TTD - (Pemberian TTD + ANC) -0.4266667 0.1614699 87 -0.8116884
## upper.CL t.ratio p.value
## -0.2783116 -4.108 0.0003
## -0.7049782 -6.750 <0.0001
## -0.0416449 -2.642 0.0262
##
## waktu = TM3:
## contrast estimate SE df lower.CL
## Kontrol - Pemberian TTD -1.0933333 0.1578778 87 -1.4697898
## Kontrol - (Pemberian TTD + ANC) -1.3800000 0.1578778 87 -1.7564565
## Pemberian TTD - (Pemberian TTD + ANC) -0.2866667 0.1578778 87 -0.6631232
## upper.CL t.ratio p.value
## -0.7168768 -6.925 <0.0001
## -1.0035435 -8.741 <0.0001
## 0.0897898 -1.816 0.1705
##
## Confidence level used: 0.95
## Conf-level adjustment: tukey method for comparing a family of 3 estimates
## P value adjustment: tukey method for comparing a family of 3 estimates
##
## >>> 9. LMM dengan semua pengukuran tersedia
## model n_observasi AIC BIC singular konvergensi
## 1 random_intercept 360 164.6389 219.0444 FALSE
## 2 random_intercept_slope 360 168.5489 230.7266 FALSE
## Linear mixed model fit by REML. t-tests use Satterthwaite's method [
## lmerModLmerTest]
## Formula: Hb ~ kelompok * waktu + (1 | id)
## Data: long_obs
## Control: lmerControl(optimizer = "bobyqa")
##
## REML criterion at convergence: 136.6
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.17750 -0.56714 0.00529 0.54743 2.94272
##
## Random effects:
## Groups Name Variance Std.Dev.
## id (Intercept) 0.34550 0.5878
## Residual 0.02742 0.1656
## Number of obs: 360, groups: id, 90
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 9.23806 0.06257 87.00002 147.643 < 2e-16 ***
## kelompok1 -0.43306 0.08849 87.00002 -4.894 4.50e-06 ***
## kelompok2 0.10361 0.08849 87.00002 1.171 0.2448
## waktu1 -0.47806 0.01512 260.99999 -31.628 < 2e-16 ***
## waktu2 -0.16472 0.01512 260.99999 -10.898 < 2e-16 ***
## waktu3 0.18639 0.01512 260.99999 12.331 < 2e-16 ***
## kelompok1:waktu1 0.40972 0.02138 260.99999 19.167 < 2e-16 ***
## kelompok2:waktu1 -0.10028 0.02138 260.99999 -4.691 4.39e-06 ***
## kelompok1:waktu2 0.13306 0.02138 260.99999 6.225 1.92e-09 ***
## kelompok2:waktu2 -0.04028 0.02138 260.99999 -1.884 0.0606 .
## kelompok1:waktu3 -0.15139 0.02138 260.99999 -7.082 1.32e-11 ***
## kelompok2:waktu3 -0.02472 0.02138 260.99999 -1.157 0.2485
## ---
## 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
## Groups Name Std.Dev.
## id (Intercept) 0.58779
## Residual 0.16558
## efek Sum Sq Mean Sq NumDF DenDF F value Pr(>F)
## 1 kelompok 0.7161595 0.3580797 2 87 13.06096 1.095979e-05
## 2 waktu 44.8831868 14.9610623 3 261 545.70493 4.267270e-112
## 3 kelompok:waktu 17.6337222 2.9389537 6 261 107.19837 1.685124e-67
## # Intraclass Correlation Coefficient
##
## Adjusted ICC: 0.926
## Unadjusted ICC: 0.532
##
## >>> 10. Diagnostik LMM

## Grafik tersimpan: D:/2026/S2 UNMUL/TUGAS/BIOSTAT/hasil_analisis_hb/10_qq_residual.png

## Grafik tersimpan: D:/2026/S2 UNMUL/TUGAS/BIOSTAT/hasil_analisis_hb/10_residual_prediksi.png

## Grafik tersimpan: D:/2026/S2 UNMUL/TUGAS/BIOSTAT/hasil_analisis_hb/10_residual_sel.png
## [1] FALSE
## [1] TRUE
## attr(,"gradient")
## [1] 3.025428e-07
##
## >>> 11. Informasi sesi dan batas interpretasi
## R version 4.6.1 (2026-06-24 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## locale:
## [1] LC_COLLATE=English_Indonesia.utf8 LC_CTYPE=English_Indonesia.utf8
## [3] LC_MONETARY=English_Indonesia.utf8 LC_NUMERIC=C
## [5] LC_TIME=English_Indonesia.utf8
##
## time zone: Asia/Makassar
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] base64enc_0.1-6 htmltools_0.5.9 knitr_1.51 ggpubr_1.0.0
## [5] performance_0.18.2 pbkrtest_0.5.5 lmerTest_3.2-1 effectsize_1.0.3
## [9] car_3.1-5 carData_3.0-6 rstatix_1.1.0 emmeans_2.0.4
## [13] afex_1.5-1 lme4_2.0-6 Matrix_1.7-5 ggplot2_4.0.3
## [17] tidyr_1.3.2 dplyr_1.2.1
##
## loaded via a namespace (and not attached):
## [1] gtable_0.3.6 xfun_0.60 bslib_0.12.0
## [4] bayestestR_0.19.0 insight_1.5.4 lattice_0.22-9
## [7] numDeriv_2016.8-1.1 vctrs_0.7.3 tools_4.6.1
## [10] Rdpack_2.6.6 generics_0.1.4 stats4_4.6.1
## [13] datawizard_1.4.0 parallel_4.6.1 tibble_3.3.1
## [16] pkgconfig_2.0.3 RColorBrewer_1.1-3 S7_0.2.2
## [19] lifecycle_1.0.5 compiler_4.6.1 farver_2.1.2
## [22] stringr_1.6.0 textshaping_1.0.5 sass_0.4.10
## [25] yaml_2.3.12 Formula_1.2-6 pillar_1.11.1
## [28] nloptr_2.2.1 jquerylib_0.1.4 MASS_7.3-65
## [31] cachem_1.1.0 reformulas_0.4.4 boot_1.3-32
## [34] abind_1.4-8 nlme_3.1-169 tidyselect_1.2.1
## [37] digest_0.6.39 mvtnorm_1.4-2 stringi_1.8.9
## [40] reshape2_1.4.5 purrr_1.2.2 labeling_0.4.3
## [43] splines_4.6.1 fastmap_1.2.0 grid_4.6.1
## [46] cli_3.6.6 magrittr_2.0.5 broom_1.0.13
## [49] withr_3.0.3 scales_1.4.0 backports_1.5.1
## [52] estimability_2.0.0 rmarkdown_2.31 otel_0.2.0
## [55] ggsignif_0.6.4 ragg_1.5.2 evaluate_1.0.5
## [58] parameters_0.29.3 rbibutils_2.4.1 rlang_1.3.0
## [61] Rcpp_1.1.2 glue_1.8.1 rstudioapi_0.19.0
## [64] minqa_1.2.8 jsonlite_2.0.0 R6_2.6.1
## [67] plyr_1.8.9 systemfonts_1.3.2
## bagian status
## 1 1. Sumber dan kelengkapan data Selesai
## 2 2. Statistik deskriptif dan visualisasi Selesai
## 3 3. Asumsi ANOVA pada peserta lengkap Selesai
## 4 4. RM ANOVA satu kelompok Selesai
## 5 5. Post hoc satu kelompok dan tren waktu Selesai
## 6 6. Pembanding nonparametrik satu kelompok Selesai
## 7 7. Mixed Design ANOVA kelompok × waktu Selesai
## 8 7b. Visualisasi interaksi kelompok dan waktu Selesai
## 9 8. Efek sederhana dan post hoc antarkelompok Selesai
## 10 9. LMM dengan semua pengukuran tersedia Selesai
## 11 10. Diagnostik LMM Selesai
## 12 11. Informasi sesi dan batas interpretasi Selesai
## peringatan
## 1
## 2 Computation failed in `stat_summary()`.\nCaused by error in `fun.data()`:\n! The package "Hmisc" is required.
## 3
## 4
## 5
## 6
## 7
## 8 Panel(s) show a mixed within-between-design.\nError bars do not allow comparisons across all means.\nSuppress error bars with: error = "none"
## 9 NaNs produced
## 10
## 11
## 12
##
## Laporan tersedia: D:/2026/S2 UNMUL/TUGAS/BIOSTAT/hasil_analisis_hb/laporan_analisis_hb.html
## Durasi: 15.5 detik.