MANOVA

install & load library

install.packages(c("MVN", "biotools", "heplots", "car"))
## Installing packages into '/cloud/lib/x86_64-pc-linux-gnu-library/4.5'
## (as 'lib' is unspecified)
library(MVN)
## Registered S3 method overwritten by 'lme4':
##   method           from
##   na.action.merMod car
library(biotools)
## Loading required package: MASS
## ---
## biotools version 4.3
library(heplots)
## Loading required package: broom
## Warning in rgl.init(initValue, onlyNULL): RGL: unable to open X11 display
## Warning: 'rgl.init' failed, will use the null device.
## See '?rgl.useNULL' for ways to avoid this warning.
## 
## Attaching package: 'heplots'
## The following object is masked from 'package:biotools':
## 
##     boxM
library(car)
## Loading required package: carData

import dataset

data <- read.csv("StudentsPerformance.csv")
head(data)
##   gender race.ethnicity parental.level.of.education        lunch
## 1 female        group B           bachelor's degree     standard
## 2 female        group C                some college     standard
## 3 female        group B             master's degree     standard
## 4   male        group A          associate's degree free/reduced
## 5   male        group C                some college     standard
## 6 female        group B          associate's degree     standard
##   test.preparation.course math.score reading.score writing.score
## 1                    none         72            72            74
## 2               completed         69            90            88
## 3                    none         90            95            93
## 4                    none         47            57            44
## 5                    none         76            78            75
## 6                    none         71            83            78

Summary seluruh data

#struktur data
str(data)
## 'data.frame':    1000 obs. of  8 variables:
##  $ gender                     : chr  "female" "female" "female" "male" ...
##  $ race.ethnicity             : chr  "group B" "group C" "group B" "group A" ...
##  $ parental.level.of.education: chr  "bachelor's degree" "some college" "master's degree" "associate's degree" ...
##  $ lunch                      : chr  "standard" "standard" "standard" "free/reduced" ...
##  $ test.preparation.course    : chr  "none" "completed" "none" "none" ...
##  $ math.score                 : int  72 69 90 47 76 71 88 40 64 38 ...
##  $ reading.score              : int  72 90 95 57 78 83 95 43 64 60 ...
##  $ writing.score              : int  74 88 93 44 75 78 92 39 67 50 ...
#ringkasan statistik seluruh variabel
summary(data)
##     gender          race.ethnicity     parental.level.of.education
##  Length:1000        Length:1000        Length:1000                
##  Class :character   Class :character   Class :character           
##  Mode  :character   Mode  :character   Mode  :character           
##                                                                   
##                                                                   
##                                                                   
##     lunch           test.preparation.course   math.score     reading.score   
##  Length:1000        Length:1000             Min.   :  0.00   Min.   : 17.00  
##  Class :character   Class :character        1st Qu.: 57.00   1st Qu.: 59.00  
##  Mode  :character   Mode  :character        Median : 66.00   Median : 70.00  
##                                             Mean   : 66.09   Mean   : 69.17  
##                                             3rd Qu.: 77.00   3rd Qu.: 79.00  
##                                             Max.   :100.00   Max.   :100.00  
##  writing.score   
##  Min.   : 10.00  
##  1st Qu.: 57.75  
##  Median : 69.00  
##  Mean   : 68.05  
##  3rd Qu.: 79.00  
##  Max.   :100.00

Ringkasan data digunakan untuk memberikan gambaran awal mengenai karakteristik dataset yang digunakan dalam penelitian. Informasi yang ditampilkan meliputi nilai minimum, maksimum, rata-rata, serta distribusi data pada masing-masing variabel. Dengan melihat hasil ini, peneliti dapat memahami kondisi umum data sebelum dilakukan analisis lebih lanjut.

summary khusus variabel numerik

#variabel numerik
numeric_data <- data[, c("math.score", "reading.score", "writing.score")]

summary(numeric_data)
##    math.score     reading.score    writing.score   
##  Min.   :  0.00   Min.   : 17.00   Min.   : 10.00  
##  1st Qu.: 57.00   1st Qu.: 59.00   1st Qu.: 57.75  
##  Median : 66.00   Median : 70.00   Median : 69.00  
##  Mean   : 66.09   Mean   : 69.17   Mean   : 68.05  
##  3rd Qu.: 77.00   3rd Qu.: 79.00   3rd Qu.: 79.00  
##  Max.   :100.00   Max.   :100.00   Max.   :100.00

Ringkasan variabel numerik memberikan informasi statistik deskriptif yang lebih fokus pada nilai akademik siswa. Hal ini membantu dalam memahami pola distribusi nilai serta melihat apakah terdapat indikasi nilai ekstrem atau ketidakseimbangan data.

visualisasi boxplot

boxplot(numeric_data,
        main = "Distribusi Nilai Siswa",
        ylab = "Score",
        col = c("lightblue", "lightgreen", "lightpink"))

Boxplot digunakan untuk memvisualisasikan distribusi data serta mendeteksi adanya outlier. Setiap box menunjukkan median, kuartil, serta rentang nilai dari masing-masing variabel. Dari grafik ini dapat dilihat bahwa distribusi nilai antar mata pelajaran relatif serupa, meskipun terdapat beberapa variasi pada nilai ekstrem.

boxplot berdasarkan gender

boxplot(math.score ~ gender, data = data,
        main = "Math Score berdasarkan Gender",
        xlab = "Gender", ylab = "Math Score",
        col = c("lightblue", "lightpink"))

boxplot(reading.score ~ gender, data = data,
        main = "Reading Score berdasarkan Gender",
        xlab = "Gender", ylab = "Reading Score",
        col = c("lightblue", "lightpink"))

boxplot(writing.score ~ gender, data = data,
        main = "Writing Score berdasarkan Gender",
        xlab = "Gender", ylab = "Writing Score",
        col = c("lightblue", "lightpink"))

Visualisasi ini menunjukkan distribusi nilai siswa berdasarkan jenis kelamin. Perbedaan median dan penyebaran data antar kelompok dapat memberikan indikasi awal apakah terdapat perbedaan performa akademik antara siswa laki-laki dan perempuan.

Boxplot Berdasarkan Kursus Persiapan

boxplot(math.score ~ test.preparation.course, data = data,
        main = "Math Score berdasarkan Kursus Persiapan",
        xlab = "Course", ylab = "Math Score",
        col = c("orange", "lightgreen"))

boxplot(reading.score ~ test.preparation.course, data = data,
        main = "Reading Score berdasarkan Kursus Persiapan",
        xlab = "Course", ylab = "Reading Score",
        col = c("orange", "lightgreen"))

boxplot(writing.score ~ test.preparation.course, data = data,
        main = "Writing Score berdasarkan Kursus Persiapan",
        xlab = "Course", ylab = "Writing Score",
        col = c("orange", "lightgreen"))

Boxplot ini digunakan untuk melihat pengaruh partisipasi dalam kursus persiapan terhadap distribusi nilai siswa. Perbedaan median antar kelompok dapat menjadi indikasi awal adanya pengaruh dari kursus terhadap performa akademik.

preprocessing data

# Ubah variabel kategorik menjadi factor
data$gender <- as.factor(data$gender)
data$test.preparation.course <- as.factor(data$test.preparation.course)

# Cek struktur
str(data)
## 'data.frame':    1000 obs. of  8 variables:
##  $ gender                     : Factor w/ 2 levels "female","male": 1 1 1 2 2 1 1 2 2 1 ...
##  $ race.ethnicity             : chr  "group B" "group C" "group B" "group A" ...
##  $ parental.level.of.education: chr  "bachelor's degree" "some college" "master's degree" "associate's degree" ...
##  $ lunch                      : chr  "standard" "standard" "standard" "free/reduced" ...
##  $ test.preparation.course    : Factor w/ 2 levels "completed","none": 2 1 2 2 2 2 1 2 1 2 ...
##  $ math.score                 : int  72 69 90 47 76 71 88 40 64 38 ...
##  $ reading.score              : int  72 90 95 57 78 83 95 43 64 60 ...
##  $ writing.score              : int  74 88 93 44 75 78 92 39 67 50 ...

definisi variabel penelitian

#variabel multivariat
Y <- data[, c("math.score", "reading.score", "writing.score")]

#variabel independen
X1 <- data$gender
X2 <- data$test.preparation.course

eksplorasi data awal

# Statistik deskriptif
summary(Y)
##    math.score     reading.score    writing.score   
##  Min.   :  0.00   Min.   : 17.00   Min.   : 10.00  
##  1st Qu.: 57.00   1st Qu.: 59.00   1st Qu.: 57.75  
##  Median : 66.00   Median : 70.00   Median : 69.00  
##  Mean   : 66.09   Mean   : 69.17   Mean   : 68.05  
##  3rd Qu.: 77.00   3rd Qu.: 79.00   3rd Qu.: 79.00  
##  Max.   :100.00   Max.   :100.00   Max.   :100.00
# Korelasi antar variabel dependen
cor(Y)
##               math.score reading.score writing.score
## math.score     1.0000000     0.8175797     0.8026420
## reading.score  0.8175797     1.0000000     0.9545981
## writing.score  0.8026420     0.9545981     1.0000000
# Scatterplot matrix
pairs(Y)

cek missing value & standarisasi data

colSums(is.na(data))
##                      gender              race.ethnicity 
##                           0                           0 
## parental.level.of.education                       lunch 
##                           0                           0 
##     test.preparation.course                  math.score 
##                           0                           0 
##               reading.score               writing.score 
##                           0                           0
Y_scaled <- scale(Y)

Uji Normalitas Multivariat (Mardia)

mvn_result <- MVN::mvn(data = Y, mvn_test = "mardia")

#output
summary(mvn_result)
## 
## ── Multivariate Normality Test Results ─────────────────────────────────────────
##              Test Statistic p.value     Method          MVN
## 1 Mardia Skewness    30.255  <0.001 asymptotic ✗ Not normal
## 2 Mardia Kurtosis    -2.266   0.023 asymptotic ✗ Not normal
## 
## ── Univariate Normality Test Results ───────────────────────────────────────────
##               Test      Variable Statistic p.value    Normality
## 1 Anderson-Darling    math.score     0.657   0.086     ✓ Normal
## 2 Anderson-Darling reading.score     1.021   0.011 ✗ Not normal
## 3 Anderson-Darling writing.score     1.447  <0.001 ✗ Not normal
## 
## ── Descriptive Statistics ──────────────────────────────────────────────────────
##        Variable    n   Mean Std.Dev Median Min Max  25th 75th   Skew Kurtosis
## 1    math.score 1000 66.089  15.163     66   0 100 57.00   77 -0.279    3.268
## 2 reading.score 1000 69.169  14.600     70  17 100 59.00   79 -0.259    2.926
## 3 writing.score 1000 68.054  15.196     69  10 100 57.75   79 -0.289    2.961

Analisis diawali dengan pengujian asumsi normalitas multivariat menggunakan metode Mardia. Hasil pengujian menunjukkan bahwa nilai p-value pada skewness dan kurtosis berada di bawah taraf signifikansi 0,05. Hal ini mengindikasikan bahwa data tidak memenuhi asumsi normalitas multivariat. Meskipun demikian, kondisi ini masih dapat ditoleransi dalam analisis MANOVA karena ukuran sampel yang besar, sehingga metode ini tetap robust terhadap pelanggaran asumsi normalitas.

Uji Dependensi (Korelasi)

cor_matrix <- cor(Y)
cor_matrix
##               math.score reading.score writing.score
## math.score     1.0000000     0.8175797     0.8026420
## reading.score  0.8175797     1.0000000     0.9545981
## writing.score  0.8026420     0.9545981     1.0000000

Selanjutnya, dilakukan pengujian dependensi antar variabel dependen melalui matriks korelasi. Hasil korelasi menunjukkan adanya hubungan antar variabel nilai matematika, membaca, dan menulis dengan tingkat korelasi yang tidak terlalu tinggi. Hal ini menunjukkan bahwa variabel-variabel tersebut saling berkaitan namun tidak mengalami multikolinearitas yang berlebihan, sehingga layak dianalisis secara simultan dalam MANOVA.

Uji Homogenitas Matriks Kovarians

biotools::boxM(Y, X1)
## 
##  Box's M-test for Homogeneity of Covariance Matrices
## 
## data:  Y
## Chi-Sq (approx.) = 9.2549, df = 6, p-value = 0.1597
biotools::boxM(Y, X2)
## 
##  Box's M-test for Homogeneity of Covariance Matrices
## 
## data:  Y
## Chi-Sq (approx.) = 12.474, df = 6, p-value = 0.05219
biotools::boxM(Y, interaction(X1, X2))
## 
##  Box's M-test for Homogeneity of Covariance Matrices
## 
## data:  Y
## Chi-Sq (approx.) = 35.901, df = 18, p-value = 0.007264

Pengujian berikutnya adalah uji homogenitas matriks kovarians menggunakan Box’s M Test. Uji ini bertujuan untuk mengetahui apakah varians dan kovarians antar kelompok bersifat homogen. Apabila nilai p-value lebih besar dari 0,05, maka asumsi homogenitas terpenuhi. Sebaliknya, jika p-value lebih kecil dari 0,05, maka asumsi tidak terpenuhi, namun analisis MANOVA masih dapat dilanjutkan karena sifatnya yang cukup robust.

One-Way MANOVA

manova_model <- manova(
  cbind(math.score, reading.score, writing.score) ~ gender,
  data = data
)

summary(manova_model, test = "Wilks")
##            Df   Wilks approx F num Df den Df    Pr(>F)    
## gender      1 0.43419   432.63      3    996 < 2.2e-16 ***
## Residuals 998                                             
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Analisis MANOVA dilakukan menggunakan pendekatan One-Way MANOVA dengan mempertimbangkan satu variabel independen yaitu jenis kelamin. Pendekatan ini digunakan untuk menguji apakah terdapat perbedaan performa akademik siswa berdasarkan gender terhadap kombinasi nilai matematika, membaca, dan menulis.

Uji Lanjutan (ANOVA Univariat)

summary.aov(manova_model)
##  Response math.score :
##              Df Sum Sq Mean Sq F value   Pr(>F)    
## gender        1   6481  6481.4  28.979 9.12e-08 ***
## Residuals   998 223208   223.7                     
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##  Response reading.score :
##              Df Sum Sq Mean Sq F value    Pr(>F)    
## gender        1  12711 12710.8  63.351 4.681e-15 ***
## Residuals   998 200242   200.6                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##  Response writing.score :
##              Df Sum Sq Mean Sq F value    Pr(>F)    
## gender        1  20931 20930.8  99.592 < 2.2e-16 ***
## Residuals   998 209746   210.2                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Untuk mengetahui variabel dependen mana yang paling berpengaruh, dilakukan uji lanjutan berupa ANOVA univariat. Hasil ini memberikan informasi lebih rinci terkait pengaruh masing-masing variabel independen terhadap setiap skor ujian.

Visualisasi Distribusi Data Boxplot

boxplot(math.score ~ gender, data = data,
        main = "Distribusi Nilai Matematika Berdasarkan Gender",
        xlab = "Gender", ylab = "Math Score")

boxplot(reading.score ~ gender, data = data,
        main = "Distribusi Nilai Membaca Berdasarkan Gender",
        xlab = "Gender", ylab = "Reading Score")

boxplot(writing.score ~ gender, data = data,
        main = "Distribusi Nilai Menulis Berdasarkan Gender",
        xlab = "Gender", ylab = "Writing Score")

Boxplot menunjukkan perbedaan distribusi nilai antar gender. Jika terlihat perbedaan median atau penyebaran yang mencolok, maka hal ini mengindikasikan adanya potensi perbedaan performa akademik antara kelompok.

Visualisasi Hubungan Antar Variabel (Scatter Plot Matrix)

pairs(Y, main = "Scatter Plot Matrix Nilai Siswa")

Scatter plot matrix menampilkan hubungan pasangan antar variabel dependen. Pola yang terbentuk menunjukkan adanya korelasi. Jika titik-titik membentuk pola linear, maka terdapat hubungan antar variabel, yang menjadi salah satu syarat penting dalam analisis MANOVA.

Visualisasi Multivariat

Y_scaled <- scale(data[, c("math.score", "reading.score", "writing.score")])

manova_scaled <- manova(
  Y_scaled ~ gender * test.preparation.course,
  data = data
)

heplot(manova_scaled,
       variables = c("math.score", "reading.score"),
       terms = "gender",
       col = c("darkblue", "darkred"),
       lwd = 2,
       main = "HE Plot Pengaruh Gender terhadap Performa Akademik")

HE Plot menggambarkan hubungan antara variabel dependen dalam ruang multivariat serta pengaruh variabel independen. Setelah dilakukan standarisasi data, pola distribusi menjadi lebih seimbang dan interpretasi menjadi lebih jelas. Perbedaan bentuk atau arah ellipse menunjukkan adanya pengaruh variabel independen terhadap kombinasi variabel dependen.

Setelah dilakukan analisis MANOVA, penelitian dilanjutkan dengan MANCOVA untuk memperoleh hasil yang lebih akurat dengan mengontrol variabel kemampuan literasi. Pendekatan ini memungkinkan peneliti untuk memisahkan pengaruh utama dari variabel independen terhadap performa akademik siswa.

MANCOVA

menambahkan covariate

data$literacy <- (data$reading.score + data$writing.score) / 2
summary(data$literacy)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   13.50   58.50   69.50   68.61   79.00  100.00

Pada tahap ini ditambahkan variabel kovariat berupa kemampuan literasi yang diperoleh dari rata-rata nilai membaca dan menulis. Variabel ini digunakan untuk mengontrol pengaruh kemampuan dasar siswa terhadap performa akademik secara keseluruhan.

model one way mancova

mancova_model <- manova(
  cbind(math.score, reading.score) ~ gender + literacy,
  data = data
)

summary(mancova_model, test = "Wilks")
##            Df    Wilks approx F num Df den Df    Pr(>F)    
## gender      1 0.268800   1354.7      2    996 < 2.2e-16 ***
## literacy    1 0.020503  23790.6      2    996 < 2.2e-16 ***
## Residuals 997                                              
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Analisis MANCOVA dilakukan dengan menggunakan dua variabel dependen, yaitu nilai matematika dan membaca, serta satu variabel kovariat berupa kemampuan literasi. Variabel menulis tidak dimasukkan dalam model karena digunakan dalam pembentukan variabel kovariat, sehingga untuk menghindari multikolinearitas, variabel tersebut dikeluarkan dari analisis.

uji lanjutan

summary.aov(mancova_model)
##  Response math.score :
##              Df Sum Sq Mean Sq F value    Pr(>F)    
## gender        1   6481    6481  175.61 < 2.2e-16 ***
## literacy      1 186411  186411 5050.71 < 2.2e-16 ***
## Residuals   997  36797      37                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##  Response reading.score :
##              Df Sum Sq Mean Sq F value    Pr(>F)    
## gender        1  12711   12711  2620.1 < 2.2e-16 ***
## literacy      1 195405  195405 40278.3 < 2.2e-16 ***
## Residuals   997   4837       5                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Hasil uji lanjutan menunjukkan pengaruh jenis kelamin terhadap masing-masing variabel dependen, yaitu nilai matematika dan membaca, setelah mengontrol kemampuan literasi.

Visualisasi

model_math <- lm(math.score ~ gender + literacy, data = data)

boxplot(fitted(model_math) ~ data$gender,
        main = "Adjusted Math Score by Gender",
        xlab = "Gender",
        ylab = "Adjusted Math Score")

Visualisasi menunjukkan nilai yang telah disesuaikan setelah efek literasi dikontrol. Perbedaan antar kelompok gender mencerminkan pengaruh murni dari jenis kelamin terhadap masing-masing variabel dependen tanpa dipengaruhi oleh kemampuan literasi.