library(MVTests) # OneSampleHT2
## Warning: package 'MVTests' was built under R version 4.4.3
##
## Attaching package: 'MVTests'
## The following object is masked from 'package:datasets':
##
## iris
library(Hotelling) # hotelling.test untuk 2-sample
## Loading required package: corpcor
library(MVN) # pemeriksaan normalitas multivariat (opsional)
## Warning: package 'MVN' was built under R version 4.4.3
Kasus A (paired): Evaluasi Intervensi Pembelajaran pada 30 mahasiswa. Dua indikator diukur sebelum dan sesudah: Vocab Score (skor kosa kata) dan Grammar Score (skor tata bahasa). Analisis apakah rata-rata perubahan (post − pre) pada kedua indikator berbeda dari nol secara multivariat (paired Hotelling T²).
set.seed(1090)
n = 30
pre_vocab = rnorm(n, mean = 70, sd = 8)
post_vocab = pre_vocab + rnorm(n, mean = 3.5, sd = 6)
pre_grammar = rnorm(n, mean = 65, sd = 10)
post_grammar = pre_grammar + rnorm(n, mean = 2.0, sd = 7)
paired_data = data.frame(
pre_vocab = pre_vocab,
pre_grammar = pre_grammar,
post_vocab = post_vocab,
post_grammar = post_grammar
)
paired_data
## pre_vocab pre_grammar post_vocab post_grammar
## 1 77.18196 50.84890 75.50695 60.64379
## 2 73.10376 70.07774 74.38475 67.88277
## 3 74.13816 78.89827 88.73572 63.77087
## 4 65.01245 61.88441 68.20452 68.49567
## 5 65.37584 62.82074 73.84853 65.66938
## 6 64.91233 56.37798 70.94242 61.67582
## 7 63.71890 59.09534 66.01359 57.75815
## 8 67.41605 61.15734 77.83559 57.02356
## 9 67.72266 57.30812 72.50419 63.88076
## 10 60.70177 83.67862 62.90334 91.77928
## 11 83.41712 64.02156 87.28443 62.92702
## 12 64.73610 54.74243 66.70234 56.74651
## 13 50.71791 57.91248 53.01941 61.38923
## 14 87.04831 84.05751 83.62120 92.56269
## 15 65.07411 67.70982 66.65671 82.30317
## 16 62.45229 85.18534 70.82461 89.87865
## 17 78.97607 64.72385 93.82860 57.55626
## 18 72.95628 70.61487 79.56147 67.94718
## 19 85.68471 58.65849 97.18971 51.84119
## 20 73.88657 63.36536 76.74075 59.52770
## 21 76.76474 70.56115 76.73815 75.62066
## 22 69.21405 73.35220 86.26261 74.90950
## 23 79.99606 58.45988 78.83379 73.60051
## 24 73.27583 64.45651 78.00180 67.34333
## 25 68.17264 91.55845 73.71947 97.60930
## 26 68.09586 59.08298 70.86526 56.42601
## 27 91.52704 71.48786 81.34837 79.48181
## 28 70.20879 53.09069 84.78909 57.63369
## 29 70.08932 51.43392 70.10330 60.11073
## 30 76.49248 59.58294 87.24836 50.24390
d_vocab = paired_data$post_vocab - paired_data$pre_vocab
d_grammar = paired_data$post_grammar - paired_data$pre_grammar
X_paired = data.frame(d_vocab, d_grammar)
xbar_p = apply(X_paired, 2, mean)
cov_p = cov(X_paired)
n_p = nrow(X_paired)
xbar_p
## d_vocab d_grammar
## 4.871628 2.267778
cov_p
## d_vocab d_grammar
## d_vocab 36.66519 -25.18874
## d_grammar -25.18874 47.70832
Interpretasi Hasil:
d_vocab = 4.87 → rata-rata skor vocabulary setelah – sebelum naik cukup besar.
d_grammar = 2.27 → grammar juga naik, tapi lebih kecil dibanding vocab.
Varians d_vocab = 36.67, varians d_grammar = 47.71 → penyebaran nilai grammar lebih besar.
Kovarians = -25.19 → ada hubungan negatif, artinya kalau selisih vocabulary tinggi, biasanya selisih grammar cenderung rendah (trade-off).
mean0 = c(0,0)
res_paired = OneSampleHT2(X_paired, mu0 = mean0, alpha = 0.05)
summary(res_paired)
## One Sample Hotelling T Square Test
##
## Hotelling T Sqaure Statistic = 50.52301
## F value = 24.39 , df1 = 2 , df2 = 28 , p-value: 7.36e-07
##
## Descriptive Statistics
##
## d_vocab d_grammar
## N 30.000000 30.000000
## Means 4.871628 2.267778
## Sd 6.055179 6.907121
##
##
## Detection important variable(s)
##
## Lower Upper Mu0 Important Variables?
## d_vocab 1.963593 7.779663 0 *TRUE*
## d_grammar -1.049407 5.584963 0 FALSE
Interpretasi Hasil:
Hasilnya menolak H0 → minimal ada satu komponen mean yang beda signifikan dari nol.
Jadi, secara multivariat, ada bukti signifikan bahwa skor setelah – sebelum tidak sama dengan nol.
res_paired$CI
## Lower Upper Mu0 Important Variables?
## d_vocab 1.963593 7.779663 0 *TRUE*
## d_grammar -1.049407 5.584963 0 FALSE
bon = function(mu, S, n, alpha, k){
p = length(mu)
lower = mu[k] - sqrt(S[k,k]/n) * abs(qt(alpha/(2*p), df=n-1))
upper = mu[k] + sqrt(S[k,k]/n) * abs(qt(alpha/(2*p), df=n-1))
c(lower = lower, upper = upper)
}
# CI Bonferroni untuk d_vocab (k=1) dan d_grammar (k=2)
bon(xbar_p, cov_p, n_p, 0.05, 1)
## lower.d_vocab upper.d_vocab
## 2.258350 7.484905
bon(xbar_p, cov_p, n_p, 0.05, 2)
## lower.d_grammar upper.d_grammar
## -0.7131784 5.2487346
Interpretasi Hasil:
Untuk d_vocab:
CI Simultan: (1.96, 7.78) → seluruh interval > 0.
CI Bonferroni: (2.26, 7.48) → juga seluruh interval > 0. Jadi peningkatan vocabulary signifikan positif.
Untuk d_vocab:
CI Simultan: (-1.05, 5.58).
CI Bonferroni: (-0.71, 5.25). Interval mencakup 0 → artinya peningkatan grammar tidak signifikan.
Insight:
Program/intervensi yang diuji efektif meningkatkan vocabulary, terbukti signifikan.
Untuk grammar, meskipun ada kenaikan rata-rata, secara statistik belum bisa dipastikan signifikan → mungkin karena variasi yang besar (lihat varians grammar yang tinggi) atau ukuran sampel yang terbatas.
Korelasi negatif antara dua selisih ini juga menarik karena bisa jadi peserta fokus ke vocabulary sehingga grammar relatif kurang meningkat.
Kasus B (independent, var sama): Bandingkan dua metode pengajaran (Online vs Offline) pada dua kemampuan: StatSkill dan ProgSkill. Kita anggap ragam sama (gunakan pooled S).
set.seed(1090)
n1 = 28
n2 = 30
stat_online = rnorm(n1, mean = 75, sd = 7)
prog_online = rnorm(n1, mean = 70, sd = 8)
stat_offline = rnorm(n2, mean = 78, sd = 7)
prog_offline = rnorm(n2, mean = 73, sd = 8)
data_online = data.frame(StatSkill = stat_online, ProgSkill = prog_online)
data_offline = data.frame(StatSkill = stat_offline, ProgSkill = prog_offline)
summary(data_online)
## StatSkill ProgSkill
## Min. :58.13 Min. :60.76
## 1st Qu.:70.68 1st Qu.:68.19
## Median :74.75 Median :70.29
## Mean :76.30 Mean :72.14
## 3rd Qu.:81.01 3rd Qu.:76.49
## Max. :93.84 Max. :88.06
summary(data_offline)
## StatSkill ProgSkill
## Min. :62.04 Min. :53.43
## 1st Qu.:73.64 1st Qu.:67.67
## Median :77.09 Median :73.49
## Mean :78.99 Mean :72.51
## 3rd Qu.:83.37 3rd Qu.:78.05
## Max. :96.59 Max. :88.02
xbar1 = apply(data_online, 2, mean)
xbar2 = apply(data_offline, 2, mean)
S1 = cov(data_online)
S2 = cov(data_offline)
xbar1; xbar2
## StatSkill ProgSkill
## 76.29651 72.13875
## StatSkill ProgSkill
## 78.99313 72.50763
S1; S2
## StatSkill ProgSkill
## StatSkill 61.138311 6.039652
## ProgSkill 6.039652 45.874783
## StatSkill ProgSkill
## StatSkill 64.866945 -5.883617
## ProgSkill -5.883617 61.219167
S_pooled = ((n1-1)*S1 + (n2-1)*S2) / (n1 + n2 - 2)
S_pooled
## StatSkill ProgSkill
## StatSkill 63.069211 -0.134898
## ProgSkill -0.134898 53.820982
Interpretasi Hasil:
Rataan Tiap Grup
Grup 1 → StatSkill = 76.30, ProgSkill = 72.14
Grup 2 → StatSkill = 78.99, ProgSkill = 72.51 Perbedaan rata-rata:
StatSkill: 76.30 vs 78.99 → selisih ≈ -2.7 (grup 2 sedikit lebih tinggi).
ProgSkill: 72.14 vs 72.51 → selisih ≈ -0.37 (nyaris sama).
Matriks Kovarians:
Varian StatSkill sekitar 61–65, varian ProgSkill sekitar 46–61 → penyebaran mirip.
Kovarians relatif kecil (positif di grup 1, negatif di grup 2, hampir 0 di pooled).
Jadi asumsi “ragam sama” wajar dipakai, karena varian kedua grup tidak terlalu berbeda jauh.
t2_homogen = hotelling.test(data_online, data_offline, var.equal = TRUE)
t2_homogen
## Test stat: 1.7076
## Numerator df: 2
## Denominator df: 55
## P-value: 0.4378
Interpretasi Hasil:
Statistik uji = 1.7076, p-value = 0.4378.
Karena p-value > 0.05 → tidak ada perbedaan signifikan multivariat antara dua grup pada mean vector (StatSkill & ProgSkill).
Artinya, secara keseluruhan, performa kedua grup tidak berbeda signifikan.
T.ci = function(mu1, mu2, S_gab, n1, n2, avec = rep(1, length(mu1)), level = 0.95){
p = length(mu1)
mu = mu1 - mu2
cval = qf(level, p, n1 + n2 - p - 1) * p * (n1 + n2 - 2) / (n1 + n2 - p - 1)
zhat = crossprod(avec, mu)
zvar = crossprod(avec, S_gab %*% avec) * (1/n1 + 1/n2)
const = sqrt(cval * zvar)
c(lower = zhat - const, upper = zhat + const)
}
# Komponen 1: StatSkill
T.ci(xbar1, xbar2, S_pooled, n1, n2, avec = c(1, 0), level = 0.95)
## lower upper
## -7.994440 2.601198
# Komponen 2: ProgSkill
T.ci(xbar1, xbar2, S_pooled, n1, n2, avec = c(0, 1), level = 0.95)
## lower upper
## -5.262890 4.525116
bon2 = function(mu1, mu2, S, n1, n2, alpha, k){
p = length(mu1)
mu = mu1 - mu2
se = sqrt(S[k,k] * (1/n1 + 1/n2))
lower = mu[k] - se * abs(qt(alpha/(2*p), df = n1 + n2 - 2))
upper = mu[k] + se * abs(qt(alpha/(2*p), df = n1 + n2 - 2))
ci = c(lower = lower, upper = upper)
names(ci) = c("lower","upper")
ci
}
### Bonferroni CI
bon2(xbar1, xbar2, S_pooled, n1, n2, 0.05, 1)
## lower upper
## -7.503112 2.109870
bon2(xbar1, xbar2, S_pooled, n1, n2, 0.05, 2)
## lower upper
## -4.809012 4.071238
Interpretasi Hasil:
Untuk StatSkill:
CI Simultan: (-7.99, 2.60) → mencakup 0 → tidak signifikan.
CI Bonferroni: (-7.50, 2.11).
Untuk ProgSkill:
CI Simultan: (-5.26, 4.53) → juga mencakup 0 → tidak signifikan.
CI Bonferroni: (-4.81, 4.07).
Insight:
Perbedaan rata-rata StatSkill dan ProgSkill antar dua grup tidak signifikan secara statistik.
Meski secara deskriptif grup 2 punya nilai StatSkill sedikit lebih tinggi, bukti statistik tidak cukup untuk menyatakan ada perbedaan nyata.
Kasus C (independent, var tidak sama): Bandingkan dua grup lain dengan variansi berbeda misal Metode A vs Metode B pada dua skor yang berbeda, tanpa asumsi homogenitas.
set.seed(1090)
m = 32; # ukuran grup A
k = 26; # ukuran grup B
# Buat S1 dan S2 berbeda (sd berbeda) sehingga ragam tak sama
stat_A = rnorm(m, mean = 80, sd = 6) # grup A lebih konsisten
prog_A = rnorm(m, mean = 76, sd = 6)
data_A = data.frame(StatSkill = stat_A, ProgSkill = prog_A)
stat_B = rnorm(k, mean = 76, sd = 10) # grup B lebih variatif
prog_B = rnorm(k, mean = 72, sd = 12)
data_B = data.frame(StatSkill = stat_B, ProgSkill = prog_B)
xbarA = apply(data_A, 2, mean)
xbarB = apply(data_B, 2, mean)
S_A = cov(data_A)
S_B = cov(data_B)
xbarA; xbarB
## StatSkill ProgSkill
## 80.89558 77.54901
## StatSkill ProgSkill
## 76.55755 72.27419
S_A; S_B
## StatSkill ProgSkill
## StatSkill 41.1973448 0.4333286
## ProgSkill 0.4333286 37.6016291
## StatSkill ProgSkill
## StatSkill 112.75977 23.90728
## ProgSkill 23.90728 137.47349
Interpretasi Hasil:
Rataan Tiap Grup
Grup 1 → StatSkill = 80.90, ProgSkill = 77.55
Grup 2 → StatSkill = 76.56, ProgSkill = 72.27
Secara deskriptif, grup 1 lebih tinggi di kedua keterampilan (StatSkill selisih ≈ +4.34, ProgSkill selisih ≈ +5.28).
Matriks kovarian
Grup 1: var(StatSkill) = 41.20, var(ProgSkill) = 37.60, kovarians ≈ 0.43 → relatif stabil & seimbang.
Grup 2: var(StatSkill) = 112.76, var(ProgSkill) = 137.47, kovarians = 23.91 → penyebaran jauh lebih besar.
Jadi asumsi ragam tidak sama wajar karena varian grup 2 jauh lebih besar.
t2_not_homogen = hotelling.test(data_A, data_B, var.equal = FALSE)
t2_not_homogen
## Test stat: 6.6355
## Numerator df: 2
## Denominator df: 37.262660329707
## P-value: 0.04964
Interpretasi Hasil:
Statistik uji = 6.6355, p-value = 0.04964.
Karena p-value < 0.05 → tolak H0, artinya ada perbedaan signifikan multivariat antara dua grup pada mean vector (StatSkill & ProgSkill).
T.ci_hetero = function(mu1, mu2, S1, S2, n1, n2, avec = rep(1, length(mu1)), level = 0.95){
p = length(mu1)
mu = mu1 - mu2
cval = qchisq(level, p) # chi-square kritis
zhat = crossprod(avec, mu)
zvar = crossprod(avec, S1 %*% avec)/n1 + crossprod(avec, S2 %*% avec)/n2
const = sqrt(cval * zvar)
c(lower = zhat - const, upper = zhat + const)
}
T.ci_hetero(xbarA, xbarB, S_A, S_B, m, k, avec = c(1,0), level = 0.95)
## lower upper
## -1.46697 10.14302
T.ci_hetero(xbarA, xbarB, S_A, S_B, m, k, avec = c(0,1), level = 0.95)
## lower upper
## -0.9477033 11.4973434
Interpretasi Hasil:
StatSkill: (-1.47, 10.14) → interval masih mencakup 0 → perbedaan StatSkill tidak signifikan secara individu.
ProgSkill: (-0.95, 11.50) → juga mencakup 0 → perbedaan ProgSkill tidak signifikan secara individu.
Jadi meskipun secara gabungan signifikan (multivariat), jika dilihat satu per satu (univariat), tidak ada yang signifikan jelas. Hal ini biasa terjadi ketika ada efek gabungan kecil dari beberapa variabel.
Insight:
Secara keseluruhan (multivariat), terdapat perbedaan nyata antara dua grup pada StatSkill + ProgSkill.
Namun, ketika dilihat satu per satu, perbedaan pada masing-masing keterampilan tidak cukup kuat untuk dianggap signifikan.