# install.packages(c("car", "heplots", "pingouin", "visreg"))
library(readr)
## Warning: package 'readr' was built under R version 4.5.3
library(car)
## Warning: package 'car' was built under R version 4.5.3
## Loading required package: carData
library(heplots)
## Warning: package 'heplots' was built under R version 4.5.3
## Loading required package: broom
library(psych)
##
## Attaching package: 'psych'
## The following object is masked from 'package:car':
##
## logit
library(dplyr)
##
## Attaching package: 'dplyr'
## The following object is masked from 'package:car':
##
## recode
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(ggplot2)
##
## Attaching package: 'ggplot2'
## The following objects are masked from 'package:psych':
##
## %+%, alpha
library(MVN)
## Warning: package 'MVN' was built under R version 4.5.3
##
## Attaching package: 'MVN'
## The following object is masked from 'package:psych':
##
## mardia
df <- read_csv("Train.csv")
## Rows: 3000 Columns: 26
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (13): Gender, Blood Pressure (s/d), Physical Activity Level, Smoking Sta...
## dbl (13): Height (cm), Weight (kg), Cholesterol Level (mg/dL), BMI, Blood Gl...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
names(df) <- make.names(names(df))
df$Smoking_Status_Num <- as.numeric(as.factor(df$Smoking.Status))
df$Smoking_Status <- as.factor(df$Smoking.Status)
df_clean <- df %>%
select(
Smoking_Status,
Smoking_Status_Num,
Age = Age..years.,
Cholesterol = Cholesterol.Level..mg.dL.,
Glucose = Blood.Glucose.Level..mg.dL.
) %>%
na.omit()
Pada tahap awal, data Train.csv berhasil dimuat dengan jumlah 3.000 baris. Nama kolom kemudian dirapikan menggunakan make.names agar tidak ada spasi atau tanda khusus, sehingga lebih mudah digunakan dalam pemanggilan variabel. Variabel Smoking Status diubah menjadi tipe factor untuk menunjukkan kelompok data. Hasil akhirnya adalah dataset df_clean yang berisi variabel utama, yaitu 1 faktor (Smoking Status), 1 kovariat (Age), dan 2 variabel dependen (Cholesterol dan Glucose)
df_clean
## # A tibble: 3,000 × 5
## Smoking_Status Smoking_Status_Num Age Cholesterol Glucose
## <fct> <dbl> <dbl> <dbl> <dbl>
## 1 Former 2 89 259. 158.
## 2 Current 1 77 264. 119.
## 3 Never 3 70 208. 144.
## 4 Never 3 52 253. 137.
## 5 Former 2 79 236. 145.
## 6 Current 1 29 199. 101.
## 7 Current 1 76 246. 130.
## 8 Never 3 26 222. 117.
## 9 Former 2 50 204. 137.
## 10 Former 2 77 269. 130.
## # ℹ 2,990 more rows
print(describeBy(df_clean[, c("Cholesterol", "Glucose", "Age")],
group = df_clean$Smoking_Status, mat = TRUE))
## item group1 vars n mean sd median trimmed
## Cholesterol1 1 Current 1 793 235.01772 23.56893 235.1830 234.71797
## Cholesterol2 2 Former 1 1181 235.71566 24.67547 236.1199 235.79398
## Cholesterol3 3 Never 1 1026 231.32567 24.85547 231.5397 231.14248
## Glucose1 4 Current 2 793 127.48342 18.21799 126.9917 127.29043
## Glucose2 5 Former 2 1181 128.00814 17.94511 128.3495 128.03424
## Glucose3 6 Never 2 1026 124.45395 18.36520 124.6619 124.54039
## Age1 7 Current 3 793 57.07945 18.86843 57.0000 57.26142
## Age2 8 Former 3 1181 55.80864 19.73332 56.0000 56.00212
## Age3 9 Never 3 1026 48.03411 21.64782 46.0000 47.02311
## mad min max range skew kurtosis
## Cholesterol1 24.34295 162.79104 331.3006 168.5095 0.181177210 0.20284480
## Cholesterol2 24.74826 164.07831 307.9204 143.8421 -0.025313498 -0.04334136
## Cholesterol3 25.62080 148.81151 303.1247 154.3131 0.050436506 -0.18210934
## Glucose1 18.67773 78.75352 184.9938 106.2402 0.124310053 -0.16523758
## Glucose2 18.34126 73.93323 185.7361 111.8029 0.001358811 -0.21565543
## Glucose3 18.02917 69.86688 180.9044 111.0375 -0.032548816 -0.17330628
## Age1 23.72160 18.00000 89.0000 71.0000 -0.057112336 -1.09671133
## Age2 25.20420 18.00000 89.0000 71.0000 -0.042531114 -1.14310053
## Age3 28.16940 18.00000 89.0000 71.0000 0.294195602 -1.22160087
## se
## Cholesterol1 0.8369571
## Cholesterol2 0.7180266
## Cholesterol3 0.7759761
## Glucose1 0.6469397
## Glucose2 0.5221812
## Glucose3 0.5733529
## Age1 0.6700376
## Age2 0.5742160
## Age3 0.6758347
Hasil menunjukkan bahwa rata-rata kadar kolesterol berada di sekitar 231–235 mg/dL dan gula darah di sekitar 124–128 mg/dL untuk semua kelompok. Nilai skewness dan kurtosis yang mendekati nol menunjukkan bahwa data cenderung simetris, sehingga menjadi tanda awal bahwa data berdistribusi normal
par(mfrow=c(1,2))
boxplot(Cholesterol ~ Smoking_Status, data = df_clean, col = "skyblue",
main = "Boxplot Kolesterol", xlab = "Status Merokok")
boxplot(Glucose ~ Smoking_Status, data = df_clean, col = "salmon",
main = "Boxplot Gula Darah", xlab = "Status Merokok")
par(mfrow=c(1,1))
Visualisasi boxplot menunjukkan bahwa distribusi kadar kolesterol dan gula darah pada ketiga kelompok status merokok terlihat cukup mirip, namun tetap ada beberapa hal penting yang perlu diperhatikan. Pada variabel kolesterol (warna biru), garis median dari ketiga kelompok berada pada posisi yang hampir sama, yaitu di sekitar 231 hingga 235 mg/dL. Hal ini menunjukkan bahwa tidak ada perbedaan nilai tengah yang mencolok antar kelompok. Selain itu, ukuran kotak atau Rentang Interkuartil (IQR) yang hampir sama pada kelompok Current, Former, dan Never juga menunjukkan bahwa variasi data antar kelompok cenderung seragam, sehingga asumsi homogenitas varians kemungkinan besar terpenuhi
Pada variabel gula darah (warna salmon), pola distribusinya terlihat cukup simetris karena garis median berada di tengah kotak. Hal ini mendukung hasil uji normalitas Shapiro-Wilk sebelumnya. Meskipun nilai median antar kelompok hampir sama, terlihat bahwa kelompok perokok (Current) dan mantan perokok (Former) sedikit lebih tinggi dibandingkan kelompok yang tidak pernah merokok. Ini bisa menjadi tanda awal bahwa status merokok mungkin berpengaruh terhadap kadar gula darah, sehingga perlu diuji lebih lanjut pada analisis berikutnya
Selain itu, adanya beberapa titik di luar garis whisker pada kedua variabel menunjukkan adanya data pencilan (outlier). Hal ini mendukung langkah pembersihan data menggunakan metode Mahalanobis Distance yang telah dilakukan sebelumnya. Outlier tersebut perlu ditangani agar tidak memengaruhi hasil analisis. Secara keseluruhan, boxplot ini menunjukkan bahwa data sudah cukup siap untuk dianalisis lebih lanjut karena distribusinya cenderung simetris, variansnya seragam, dan outlier sudah teridentifikasi dengan baik
print(cor(df_clean[, c("Cholesterol", "Glucose")]))
## Cholesterol Glucose
## Cholesterol 1.0000000 0.1895891
## Glucose 0.1895891 1.0000000
Nilai korelasi sebesar 0.189 menunjukkan adanya hubungan positif yang lemah antara kolesterol dan gula darah. Dalam analisis MANOVA, variabel dependen memang sebaiknya memiliki hubungan, tidak boleh nol tetapi juga tidak boleh terlalu tinggi agar tidak terjadi multikolinearitas dan analisis tetap efektif
print(shapiro.test(df_clean$Cholesterol))
##
## Shapiro-Wilk normality test
##
## data: df_clean$Cholesterol
## W = 0.9995, p-value = 0.6622
print(shapiro.test(df_clean$Glucose))
##
## Shapiro-Wilk normality test
##
## data: df_clean$Glucose
## W = 0.99917, p-value = 0.1804
Kolesterol (p = 0.6622) dan gula darah (p = 0.1804) sama-sama memiliki nilai p lebih dari 0.05. Artinya, secara masing-masing, kedua variabel dependen sudah memenuhi asumsi normalitas
mardia(df_clean[, c("Cholesterol", "Glucose")])
## Test Statistic p.value Method
## 1 Mardia Skewness 1.947703 0.7453773 asymptotic
## 2 Mardia Kurtosis -1.157075 0.2472418 asymptotic
Hasil uji menunjukkan bahwa nilai p untuk skewness (0.745) dan kurtosis (0.247) lebih dari 0.05. Hal ini menunjukkan bahwa data sudah memenuhi asumsi normalitas multivariat, sehingga analisis MANOVA/MANCOVA dapat dilanjutkan
m_dist <- mahalanobis(df_clean[, c("Cholesterol", "Glucose")],
colMeans(df_clean[, c("Cholesterol", "Glucose")]),
cov(df_clean[, c("Cholesterol", "Glucose")]))
cutoff <- qchisq(1-0.001, df=2)
outliers <- which(m_dist > cutoff)
cat("Ditemukan", length(outliers), "baris outlier.\n")
## Ditemukan 2 baris outlier.
hapus outlier
if(length(outliers) > 0) {
df_final <- df_clean[-outliers, ]
} else {
df_final <- df_clean
}
Berdasarkan batas nilai Chi-Square, ditemukan 2 data yang termasuk outlier multivariat. Data tersebut kemudian dihapus untuk membentuk df_final, agar hasil analisis selanjutnya tidak dipengaruhi oleh nilai yang terlalu ekstrem
print(leveneTest(Cholesterol ~ Smoking_Status, data = df_final))
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 2 1.9153 0.1475
## 2995
print(leveneTest(Glucose ~ Smoking_Status, data = df_final))
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 2 0.0944 0.9099
## 2995
Variabel kolesterol (p = 0.1475) dan gula darah (p = 0.9099) sama-sama memiliki nilai p lebih dari 0.05. Artinya, varians antar kelompok pada masing-masing variabel adalah sama atau homogen
res_boxm <- boxM(cbind(df_final$Cholesterol, df_final$Glucose), df_final$Smoking_Status)
print(res_boxm)
##
## Box's M-test for Homogeneity of Covariance Matrices
##
## data: cbind(df_final$Cholesterol, df_final$Glucose) by df_final$Smoking_Status
## Chi-Sq (approx.) = 5.1235, df = 6, p-value = 0.5281
Nilai p = 0.5281 (lebih dari 0.05) menunjukkan bahwa matriks kovarians antar kelompok adalah sama atau homogen. Hal ini menunjukkan bahwa salah satu asumsi dalam MANCOVA sudah terpenuhi, sehingga penggunaan statistik Wilks’ Lambda nantinya dapat dianggap valid
print(ggplot(df_final, aes(x = Age, y = Cholesterol, color = Smoking_Status)) +
geom_point(alpha = 0.2) + geom_smooth(method = "lm", se = FALSE) +
labs(title = "Uji Linieritas: Age vs Cholesterol", x = "Usia", y = "Kolesterol") +
theme_minimal())
## `geom_smooth()` using formula = 'y ~ x'
Visualisasi uji linearitas ini digunakan untuk melihat hubungan antara variabel kontrol (usia) dan variabel dependen (kolesterol) pada setiap kelompok status merokok. Dari grafik scatter plot, terlihat bahwa data tersebar cukup luas tetapi tetap mengikuti pola tertentu yang ditunjukkan oleh garis regresi pada masing-masing kelompok (Current, Former, dan Never). Ketiga garis tersebut menunjukkan tren linear positif, artinya kadar kolesterol cenderung meningkat seiring bertambahnya usia, tanpa dipengaruhi oleh status merokok
Hal penting dalam asumsi MANCOVA adalah adanya hubungan linear dan arah hubungan yang serupa antar kelompok. Pada grafik ini, terlihat bahwa ketiga garis regresi memiliki kemiringan yang hampir sama (sejajar) dan tidak saling berpotongan secara mencolok. Ini menunjukkan bahwa tidak ada interaksi yang signifikan antara usia dan status merokok terhadap kadar kolesterol. Dengan kata lain, pengaruh usia terhadap kolesterol konsisten di semua kelompok
Secara keseluruhan, grafik ini menunjukkan bahwa variabel usia layak digunakan sebagai kovariat dalam model MANCOVA. Hubungan linear yang stabil ini memastikan bahwa pengaruh usia dapat dikontrol dengan baik, sehingga perbedaan kadar kolesterol akibat status merokok dapat terlihat lebih jelas tanpa dipengaruhi oleh perbedaan usia