Dosen Pembimbing: Ike Fitriyaningsih, M.Si
NIDN : 0109049001
Kelas : 2023E
Dokumen ini memuat hasil analisis MANCOVA pada dataset Adult
Income dari UCI. Tujuan dari analisis ini adalah untuk mengetahui
pengaruh variabel age, occupation, dan
income terhadap dua variabel dependen yaitu
capital.gain dan capital.loss.
Seluruh proses analisis mencakup: pembersihan data, pengujian asumsi MANCOVA (normalitas, homogenitas varians, dll), transformasi data, dan interpretasi hasil.
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.4.3
## Warning: package 'ggplot2' was built under R version 4.4.3
## Warning: package 'tibble' was built under R version 4.4.3
## Warning: package 'tidyr' was built under R version 4.4.3
## Warning: package 'readr' was built under R version 4.4.3
## Warning: package 'purrr' was built under R version 4.4.3
## Warning: package 'dplyr' was built under R version 4.4.3
## Warning: package 'stringr' was built under R version 4.4.3
## Warning: package 'forcats' was built under R version 4.4.3
## Warning: package 'lubridate' was built under R version 4.4.3
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.0.4
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(car)
## Warning: package 'car' was built under R version 4.4.3
## Loading required package: carData
## Warning: package 'carData' was built under R version 4.4.3
##
## Attaching package: 'car'
##
## The following object is masked from 'package:dplyr':
##
## recode
##
## The following object is masked from 'package:purrr':
##
## some
library(MVN)
## Warning: package 'MVN' was built under R version 4.4.3
library(biotools)
## Warning: package 'biotools' was built under R version 4.4.3
## Loading required package: MASS
##
## Attaching package: 'MASS'
##
## The following object is masked from 'package:dplyr':
##
## select
##
## ---
## biotools version 4.3
library(ggpubr)
## Warning: package 'ggpubr' was built under R version 4.4.3
Memanggil pustaka-pustaka yang dibutuhkan seperti tidyverse (manipulasi data), car (analisis ANOVA/MANCOVA), MVN (uji normalitas multivariat), biotools (uji Box’s M), dan ggpubr (grafik).
df <- read.csv("C:/Users/HP 430 G5/OneDrive/Dokumen/Semester 4/Analisis Multivariat/adult.csv", stringsAsFactors = TRUE)
cat("Struktur data awal:\n")
## Struktur data awal:
str(df)
## 'data.frame': 32561 obs. of 15 variables:
## $ age : int 90 82 66 54 41 34 38 74 68 41 ...
## $ workclass : Factor w/ 9 levels "?","Federal-gov",..: 1 5 1 5 5 5 5 8 2 5 ...
## $ fnlwgt : int 77053 132870 186061 140359 264663 216864 150601 88638 422013 70037 ...
## $ education : Factor w/ 16 levels "10th","11th",..: 12 12 16 6 16 12 1 11 12 16 ...
## $ education.num : int 9 9 10 4 10 9 6 16 9 10 ...
## $ marital.status: Factor w/ 7 levels "Divorced","Married-AF-spouse",..: 7 7 7 1 6 1 6 5 1 5 ...
## $ occupation : Factor w/ 15 levels "?","Adm-clerical",..: 1 5 1 8 11 9 2 11 11 4 ...
## $ relationship : Factor w/ 6 levels "Husband","Not-in-family",..: 2 2 5 5 4 5 5 3 2 5 ...
## $ race : Factor w/ 5 levels "Amer-Indian-Eskimo",..: 5 5 3 5 5 5 5 5 5 5 ...
## $ sex : Factor w/ 2 levels "Female","Male": 1 1 1 1 1 1 2 1 1 2 ...
## $ capital.gain : int 0 0 0 0 0 0 0 0 0 0 ...
## $ capital.loss : int 4356 4356 4356 3900 3900 3770 3770 3683 3683 3004 ...
## $ hours.per.week: int 40 18 40 40 40 45 40 20 40 60 ...
## $ native.country: Factor w/ 42 levels "?","Cambodia",..: 40 40 40 40 40 40 40 40 40 1 ...
## $ income : Factor w/ 2 levels "<=50K",">50K": 1 1 1 1 1 1 1 2 1 2 ...
cat("\n5 baris pertama dari data:\n")
##
## 5 baris pertama dari data:
head(df, 5)
## age workclass fnlwgt education education.num marital.status
## 1 90 ? 77053 HS-grad 9 Widowed
## 2 82 Private 132870 HS-grad 9 Widowed
## 3 66 ? 186061 Some-college 10 Widowed
## 4 54 Private 140359 7th-8th 4 Divorced
## 5 41 Private 264663 Some-college 10 Separated
## occupation relationship race sex capital.gain capital.loss
## 1 ? Not-in-family White Female 0 4356
## 2 Exec-managerial Not-in-family White Female 0 4356
## 3 ? Unmarried Black Female 0 4356
## 4 Machine-op-inspct Unmarried White Female 0 3900
## 5 Prof-specialty Own-child White Female 0 3900
## hours.per.week native.country income
## 1 40 United-States <=50K
## 2 18 United-States <=50K
## 3 40 United-States <=50K
## 4 40 United-States <=50K
## 5 40 United-States <=50K
cat("\nJumlah missing value per kolom:\n")
##
## Jumlah missing value per kolom:
colSums(is.na(df) | df == " ?")
## age workclass fnlwgt education education.num
## 0 0 0 0 0
## marital.status occupation relationship race sex
## 0 0 0 0 0
## capital.gain capital.loss hours.per.week native.country income
## 0 0 0 0 0
df[df == " ?"] <- NA
cat("\nJumlah missing value setelah konversi ' ?' ke NA:\n")
##
## Jumlah missing value setelah konversi ' ?' ke NA:
colSums(is.na(df))
## age workclass fnlwgt education education.num
## 0 0 0 0 0
## marital.status occupation relationship race sex
## 0 0 0 0 0
## capital.gain capital.loss hours.per.week native.country income
## 0 0 0 0 0
Mengganti tanda ” ?” menjadi NA agar bisa dibersihkan dan dianalisis secara statistik.
df <- df[1:4000, ]
df <- na.omit(df)
cat("\nDimensi data setelah sampling dan menghapus NA:\n")
##
## Dimensi data setelah sampling dan menghapus NA:
dim(df)
## [1] 4000 15
mengambil 4000 baris pertama dari dataset untuk analisis dan menghapus baris yang memiliki nilai NA (missing value) dengan fungsi na.omit(). mengambil sampel 4000 data pertama, kita mendapatkan ukuran data yang cukup representatif untuk analisis, tapi tetap efisien dalam hal waktu dan sumber daya komputasi.
data_mancova <- df[, c("age", "hours.per.week", "occupation", "income", "capital.gain", "capital.loss")]
cat("\nStruktur data_mancova:\n")
##
## Struktur data_mancova:
str(data_mancova)
## 'data.frame': 4000 obs. of 6 variables:
## $ age : int 90 82 66 54 41 34 38 74 68 41 ...
## $ hours.per.week: int 40 18 40 40 40 45 40 20 40 60 ...
## $ occupation : Factor w/ 15 levels "?","Adm-clerical",..: 1 5 1 8 11 9 2 11 11 4 ...
## $ income : Factor w/ 2 levels "<=50K",">50K": 1 1 1 1 1 1 1 2 1 2 ...
## $ capital.gain : int 0 0 0 0 0 0 0 0 0 0 ...
## $ capital.loss : int 4356 4356 4356 3900 3900 3770 3770 3683 3683 3004 ...
capital.gain dan capital.loss → Ini adalah variabel dependen dalam analisis MANCOVA. Kita ingin melihat apakah dan bagaimana dua jenis modal finansial ini dipengaruhi oleh variabel lain secara simultan.
age → Dimasukkan sebagai kovariat, karena umur bisa memengaruhi jumlah capital gain/loss yang diperoleh seseorang, tapi bukan faktor eksperimen utama.
occupation dan income → Dimasukkan sebagai variabel independen (faktor), karena kita ingin mengetahui apakah pekerjaan dan tingkat pendapatan seseorang berpengaruh terhadap capital gain dan loss mereka.
data_mancova$occupation <- factor(data_mancova$occupation)
data_mancova$income <- factor(data_mancova$income)
cat("\nRingkasan statistik awal:\n")
##
## Ringkasan statistik awal:
summary(data_mancova)
## age hours.per.week occupation income
## Min. :17.00 Min. : 1.0 Exec-managerial :826 <=50K:1550
## 1st Qu.:34.00 1st Qu.:40.0 Prof-specialty :823 >50K :2450
## Median :42.00 Median :40.0 Sales :493
## Mean :43.31 Mean :43.9 Craft-repair :489
## 3rd Qu.:51.00 3rd Qu.:50.0 Adm-clerical :329
## Max. :90.00 Max. :99.0 Machine-op-inspct:182
## (Other) :858
## capital.gain capital.loss
## Min. : 0 Min. : 0.0
## 1st Qu.: 0 1st Qu.: 0.0
## Median : 3464 Median : 0.0
## Mean : 8688 Mean : 710.7
## 3rd Qu.: 7688 3rd Qu.:1762.0
## Max. :99999 Max. :4356.0
##
Memastikan struktur data sudah sesuai (tipe data dan distribusi kategori benar). Memberi gambaran awal mengenai penyebaran data yang akan dianalisis lebih lanjut.
normal_pre <- mvn(data_mancova[, c("capital.gain", "capital.loss")], mvnTest = "hz")
normal_pre$multivariateNormality
## Test HZ p value MVN
## 1 Henze-Zirkler 976.6442 0 NO
gunakan fungsi mvn() dari package MVN dengan metode Henze-Zirkler, yang menguji apakah gabungan dari variabel capital.gain dan capital.loss mengikuti distribusi normal multivariat.
Nilai HZ tinggi dan p-value = 0, menunjukkan penolakan terhadap normalitas multivariat. Artinya, data capital.gain dan capital.loss secara gabungan tidak terdistribusi normal.
data_mancova$capital.gain <- log1p(data_mancova$capital.gain)
data_mancova$capital.loss <- log1p(data_mancova$capital.loss)
normal_post <- mvn(data_mancova[, c("capital.gain", "capital.loss")], mvnTest = "hz")
normal_post$multivariateNormality
## Test HZ p value MVN
## 1 Henze-Zirkler 562.4332 0 NO
Karena data tidak normal, kita lakukan transformasi log1p pada kedua variabel Meskipun nilai HZ menurun setelah transformasi, p-value tetap 0 dan hasilnya masih tidak normal. Transformasi logaritmik membantu mengurangi skewness, tapi belum cukup untuk memenuhi asumsi normalitas multivariat.
data_mancova$group <- interaction(data_mancova$occupation, data_mancova$income)
group_count <- table(data_mancova$group)
valid_groups <- names(group_count[group_count >= 3])
data_valid <- data_mancova[data_mancova$group %in% valid_groups, ]
boxm_result <- boxM(data_valid[, c("capital.gain", "capital.loss")], data_valid$group)
boxm_result
##
## Box's M-test for Homogeneity of Covariance Matrices
##
## data: data_valid[, c("capital.gain", "capital.loss")]
## Chi-Sq (approx.) = 1534.4, df = 78, p-value < 2.2e-16
Uji ini mengevaluasi apakah matriks kovarians antar grup sama atau homogen Nilai p-value jauh lebih kecil dari 0.05, maka kita menolak H0 (hipotesis nol bahwa semua matriks kovarians antar grup adalah sama). Artinya, terdapat perbedaan signifikan pada matriks kovarians antar kombinasi occupation dan income.
leveneTest(capital.gain ~ occupation * income, data = data_mancova)
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 28 1.6961 0.01254 *
## 3971
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
leveneTest(capital.loss ~ occupation * income, data = data_mancova)
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 28 3.7766 8.638e-11 ***
## 3971
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Menguji apakah varians antar kelompok (gabungan occupation * income) untuk masing-masing variabel dependen (capital.gain dan capital.loss) adalah homogen.
Untuk capital.gain: F value = 1.6961 p-value = 0.01254 → Signifikan
Untuk capital.loss: F value = 3.7766 p-value = 8.638e-11 → Sangat signifikan
Kedua p-value < 0.05 → Asumsi homogenitas varians TIDAK terpenuhi untuk kedua variabel dependen. Artinya, terdapat perbedaan varians antara kelompok occupation * income pada capital.gain dan capital.loss.
scatterplotMatrix(data_mancova[, c("age", "capital.gain", "capital.loss")],
smooth = FALSE)
age vs capital.gain Tampak pola menyebar horizontal dengan garis tren
positif tapi tidak kuat. Kesimpulan: Ada indikasi hubungan linier lemah,
namun kemungkinan besar data ini tidak sepenuhnya linier.
age vs capital.loss Pola sebaran cukup horizontal, garis tren cenderung menurun. Kesimpulan: Ada sedikit indikasi hubungan negatif, namun juga tidak sepenuhnya linier.
capital.gain vs capital.loss
Sangat terlihat berpola L terbalik, menunjukkan non-linear relationship. Garis tren menurun tajam, menandakan bahwa jika salah satu tinggi, yang lain cenderung nol. Ini logis karena data sering menunjukkan orang hanya mendapat gain atau loss, jarang dua-duanya.
Hubungan antara variabel kovariat (age) dengan variabel dependen (capital.gain, capital.loss) tidak sepenuhnya linier. Pola sebar dan fitting menunjukkan bahwa asumsi linearitas tidak terpenuhi secara kuat.
lm_check <- lm(age ~ occupation + income, data = data_mancova)
vif(lm_check)
## GVIF Df GVIF^(1/(2*Df))
## occupation 1.160045 14 1.005316
## income 1.160045 1 1.077054
Hasil uji multikolinearitas menunjukkan bahwa nilai GVIF^(1/(2×Df)) untuk variabel occupation adalah 1.005 dan untuk income adalah 1.077, yang keduanya jauh di bawah ambang batas 2. Ini mengindikasikan bahwa tidak terdapat masalah multikolinearitas antara variabel-variabel independen dalam model, sehingga aman digunakan untuk analisis lebih lanjut
model <- manova(cbind(capital.gain, capital.loss) ~ age + occupation + income, data = data_mancova)
summary(model, test = "Pillai")
## Df Pillai approx F num Df den Df Pr(>F)
## age 1 0.030824 63.32 2 3982 < 2.2e-16 ***
## occupation 14 0.095792 14.31 28 7966 < 2.2e-16 ***
## income 1 0.188169 461.48 2 3982 < 2.2e-16 ***
## Residuals 3983
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Semua variabel (age, occupation, income) berpengaruh signifikan terhadap gabungan variabel dependen (trans_hours, trans_edu). p-value < 0.001 pada semuanya berarti pengaruhnya sangat signifikan secara statistik. Nilai Pillai’s trace mengukur kekuatan pengaruh: - income punya pengaruh terbesar (Pillai: 0.188) - disusul occupation dan age.
Pillai’s Trace digunakan dalam MANCOVA karena merupakan statistik yang paling robust terhadap pelanggaran asumsi, seperti normalitas multivariat dan homogenitas kovarian. Dibandingkan metode lain (seperti Wilks’ Lambda), Pillai lebih stabil saat data tidak seimbang dan lebih konservatif, sehingga mengurangi risiko kesalahan tipe I. Oleh karena itu, dalam kondisi data yang kompleks dan tidak sepenuhnya memenuhi asumsi klasik, Pillai menjadi pilihan yang paling aman untuk interpretasi hasil.
summary.aov(model)
## Response capital.gain :
## Df Sum Sq Mean Sq F value Pr(>F)
## age 1 1025 1024.7 55.8846 9.397e-14 ***
## occupation 14 552 39.4 2.1493 0.00758 **
## income 1 3292 3292.3 179.5522 < 2.2e-16 ***
## Residuals 3983 73034 18.3
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Response capital.loss :
## Df Sum Sq Mean Sq F value Pr(>F)
## age 1 487 487.30 37.6833 9.134e-10 ***
## occupation 14 140 10.02 0.7748 0.6979
## income 1 1092 1091.54 84.4104 < 2.2e-16 ***
## Residuals 3983 51506 12.93
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Hipotesis Nol (H₀): Setelah mengontrol pengaruh age, tidak terdapat perbedaan yang signifikan pada rata-rata gabungan antara capital.loss dan capital.gain berdasarkan kombinasi dari occupation, dan income. Hipotesis Alternatif (H₁): Setelah mengontrol pengaruh age, terdapat perbedaan yang signifikan pada rata-rata gabungan antara capital.loss dan capital.gain berdasarkan paling tidak satu kelompok dari occupation, atau income.
Semua variabel bermakna secara multivariat, dengan nilai p < 0.001. Maka, tolak H₀. Setelah mengontrol age, terdapat perbedaan yang signifikan dalam rata-rata gabungan antara capital.gain dan capital.loss berdasarkan paling tidak satu dari occupation, atau income.