Beton merupakan material konstruksi paling penting dalam rekayasa sipil. Kualitas beton tidak ditentukan oleh satu faktor tunggal, melainkan oleh interaksi kompleks dari berbagai komponen campuran, antara lain proporsi semen (cement), slag, abu terbang (fly ash), air (water), superplasticizer (SP), serta agregat kasar dan halus. Pemahaman tentang bagaimana faktor-faktor ini memengaruhi sifat mekanik beton secara simultan sangat penting dalam optimasi desain campuran beton.
Analisis ini menggunakan Multivariate Analysis of Variance (MANOVA), Analysis of Covariance (ANCOVA), dan Multivariate Analysis of Covariance (MANCOVA) untuk menguji apakah kelompok kadar semen (CementGroup) memberikan pengaruh yang signifikan terhadap tiga variabel respons beton sekaligus, dengan mengontrol pengaruh kandungan air (Water) sebagai kovariat.
Dataset yang digunakan dalam analisis ini adalah Concrete Slump Test Dataset yang bersumber dari UCI Machine Learning Repository (Yeh, 2007). Dataset tersebut memuat hasil pengujian 103 campuran beton dengan rincian sebagai berikut.
Variabel Input (7 variabel, satuan kg/m³): Cement, Slag, Fly ash, Water, SP (superplasticizer), Coarse Aggregate, Fine Aggregate.
Variabel Output (3 variabel): Slump (kemudahan pengerjaan beton dalam cm), Flow (kelecakan beton dalam cm), serta Compressive Strength (kuat tekan beton setelah 28 hari dalam MPa).
Data diambil dari file slump_test.data yang bersumber
dari UCI Machine Learning Repository.
data <- read.table(
"https://archive.ics.uci.edu/ml/machine-learning-databases/concrete/slump/slump_test.data",
sep = ",", header = TRUE
)
str(data)
## 'data.frame': 103 obs. of 11 variables:
## $ No : int 1 2 3 4 5 6 7 8 9 10 ...
## $ Cement : num 273 163 162 162 154 147 152 145 152 304 ...
## $ Slag : num 82 149 148 148 112 89 139 0 0 0 ...
## $ Fly.ash : num 105 191 191 190 144 115 178 227 237 140 ...
## $ Water : num 210 180 179 179 220 202 168 240 204 214 ...
## $ SP : num 9 12 16 19 10 9 18 6 6 6 ...
## $ Coarse.Aggr. : num 904 843 840 838 923 860 944 750 785 895 ...
## $ Fine.Aggr. : num 680 746 743 741 658 829 695 853 892 722 ...
## $ SLUMP.cm. : num 23 0 1 3 20 23 0 14.5 15.5 19 ...
## $ FLOW.cm. : num 62 20 20 21.5 64 55 20 58.5 51 51 ...
## $ Compressive.Strength..28.day..Mpa.: num 35 41.1 41.8 42.1 26.8 ...
summary(data) |>
kable(caption = "Statistik Deskriptif Dataset") |>
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)
| No | Cement | Slag | Fly.ash | Water | SP | Coarse.Aggr. | Fine.Aggr. | SLUMP.cm. | FLOW.cm. | Compressive.Strength..28.day..Mpa. | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Min. : 1.0 | Min. :137.0 | Min. : 0.00 | Min. : 0.0 | Min. :160.0 | Min. : 4.40 | Min. : 708.0 | Min. :640.6 | Min. : 0.00 | Min. :20.00 | Min. :17.19 | |
| 1st Qu.: 26.5 | 1st Qu.:152.0 | 1st Qu.: 0.05 | 1st Qu.:115.5 | 1st Qu.:180.0 | 1st Qu.: 6.00 | 1st Qu.: 819.5 | 1st Qu.:684.5 | 1st Qu.:14.50 | 1st Qu.:38.50 | 1st Qu.:30.90 | |
| Median : 52.0 | Median :248.0 | Median :100.00 | Median :164.0 | Median :196.0 | Median : 8.00 | Median : 879.0 | Median :742.7 | Median :21.50 | Median :54.00 | Median :35.52 | |
| Mean : 52.0 | Mean :229.9 | Mean : 77.97 | Mean :149.0 | Mean :197.2 | Mean : 8.54 | Mean : 884.0 | Mean :739.6 | Mean :18.05 | Mean :49.61 | Mean :36.04 | |
| 3rd Qu.: 77.5 | 3rd Qu.:303.9 | 3rd Qu.:125.00 | 3rd Qu.:235.9 | 3rd Qu.:209.5 | 3rd Qu.:10.00 | 3rd Qu.: 952.8 | 3rd Qu.:788.0 | 3rd Qu.:24.00 | 3rd Qu.:63.75 | 3rd Qu.:41.20 | |
| Max. :103.0 | Max. :374.0 | Max. :193.00 | Max. :260.0 | Max. :240.0 | Max. :19.00 | Max. :1049.9 | Max. :902.0 | Max. :29.00 | Max. :78.00 | Max. :58.53 |
Dataset terdiri dari 103 observasi dan 11 variabel, tanpa missing values. Kadar semen berkisar antara 137–374 kg/m³ dengan median 248 kg/m³. Kuat tekan beton bervariasi antara 17,19–58,53 MPa dengan rata-rata 36,04 MPa dan kandungan air berkisar 160–240 kg/m³ dengan rata-rata 197,2 kg/m³.
Kolom output asli memiliki nama dengan karakter khusus (spasi, tanda kurung, titik) sehingga perlu diubah agar mudah diakses dalam R.
colnames(data)[colnames(data) == "SLUMP.cm."] <- "Slump"
colnames(data)[colnames(data) == "FLOW.cm."] <- "Flow"
colnames(data)[colnames(data) == "Compressive.Strength..28.day..Mpa."] <- "CompressiveStrength"
# Matriks variabel dependen
Y <- cbind(
Slump = data$Slump,
Flow = data$Flow,
CompressiveStrength = data$CompressiveStrength
)
# Matriks variabel prediktor
X <- data[, c("Cement", "Coarse.Aggr.", "Fine.Aggr.", "Water", "SP")]
# Variabel faktor (pembagian berdasarkan nilai median)
data$CementGroup <- factor(ifelse(data$Cement < median(data$Cement), "Low", "High"))
data$SlagGroup <- factor(ifelse(data$Slag < median(data$Slag), "Low", "High"))
Variabel CementGroup dan SlagGroup dibentuk
dengan membagi data menjadi dua kelompok berdasarkan nilai median
masing-masing variabel, sehingga menghasilkan pembagian yang relatif
seimbang.
dist_tbl <- as.data.frame(table(CementGroup = data$CementGroup))
kable(dist_tbl, caption = "Distribusi Observasi per Kelompok CementGroup",
col.names = c("CementGroup", "Frekuensi")) |>
kable_styling(bootstrap_options = "striped", full_width = FALSE)
| CementGroup | Frekuensi |
|---|---|
| High | 52 |
| Low | 51 |
Pembagian menghasilkan 52 campuran beton dengan kadar semen tinggi (High, Cement ≥ 248 kg/m³) dan 51 campuran dengan kadar semen rendah (Low, Cement < 248 kg/m³).
dt <- data.frame(CementGroup = data$CementGroup, Y)
kable(head(dt, 10),
caption = "Sepuluh Baris Pertama Dataset (Variabel Dependen dan Faktor)",
digits = 3) |>
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
| CementGroup | Slump | Flow | CompressiveStrength |
|---|---|---|---|
| High | 23.0 | 62.0 | 34.99 |
| Low | 0.0 | 20.0 | 41.14 |
| Low | 1.0 | 20.0 | 41.81 |
| Low | 3.0 | 21.5 | 42.08 |
| Low | 20.0 | 64.0 | 26.82 |
| Low | 23.0 | 55.0 | 25.21 |
| Low | 0.0 | 20.0 | 38.86 |
| Low | 14.5 | 58.5 | 36.59 |
| Low | 15.5 | 51.0 | 32.71 |
| High | 19.0 | 51.0 | 38.46 |
numeric_data <- data[, sapply(data, is.numeric)]
numeric_data <- numeric_data[, !(names(numeric_data) %in% c("No"))]
boxplot(numeric_data,
las = 2,
col = "pink",
main = "Boxplot Concrete Slump Test Dataset",
ylab = "Nilai")
Boxplot seluruh variabel numerik pada Concrete Slump Test Dataset
Boxplot menunjukkan bahwa variabel Coarse.Aggr. dan
Fine.Aggr. memiliki skala yang jauh lebih besar (di atas
600 kg/m³) dibandingkan variabel lainnya, hal ini mencerminkan peran
dominan agregat dalam komposisi volume beton. Variabel Slag
dan Fly.ash memperlihatkan variasi yang lebar dan variabel
Slump menunjukkan sejumlah nilai yang mendekati nol yang
merepresentasikan campuran beton sangat kaku (kondisi yang umum dijumpai
pada beton berkadar air rendah).
pairs(cbind(Y, X),
col = "steelblue",
pch = 19,
cex = 0.55,
main = "Scatter Plot Matrix — Variabel Dependen dan Prediktor")
Matriks scatter plot variabel dependen dan prediktor utama
scatterplotMatrix(~ Slump + Flow + CompressiveStrength + Cement + Water + SP,
data = data,
main = "Scatter Plot Matrix dengan Kurva Estimasi")
Scatter plot matrix dengan estimasi distribusi dan kurva regresi
Dari matriks scatter plot, terlihat bahwa Slump dan
Flow memiliki korelasi positif yang kuat. Variabel
Water berkorelasi positif dengan Slump dan
Flow karena penambahan air meningkatkan kemudahan
pengerjaan beton. Sebaliknya, CompressiveStrength
menunjukkan kecenderungan negatif terhadap Water.
Cement memperlihatkan hubungan positif dengan
CompressiveStrength, memvalidasi peran semen sebagai
komponen utama penentu kekuatan beton.
MANOVA mengasumsikan bahwa kombinasi linear dari variabel-variabel dependen berdistribusi normal multivariat di setiap kelompok.
sw_result <- mshapiro.test(t(Y))
sw_tbl <- data.frame(
Uji = "Shapiro-Wilk Multivariat",
Statistik = round(sw_result$statistic, 5),
`p-value` = round(sw_result$p.value, 5),
Keputusan = ifelse(sw_result$p.value > 0.05, "Normal", "Tidak Normal"),
check.names = FALSE
)
kable(sw_tbl, caption = "Hasil Uji Shapiro-Wilk Multivariat") |>
kable_styling(bootstrap_options = "striped", full_width = FALSE)
| Uji | Statistik | p-value | Keputusan | |
|---|---|---|---|---|
| W | Shapiro-Wilk Multivariat | 0.97816 | 0.08616 | Normal |
Uji Shapiro-Wilk multivariat menghasilkan W = 0,978 dengan p-value = 0,086. Karena p > 0,05, H₀ tidak ditolak, data secara multivariat dinyatakan berdistribusi normal menurut uji ini. Kombinasi linear dari ketiga variabel dependen (Slump, Flow, dan CompressiveStrength) secara bersama-sama memenuhi asumsi normalitas multivariat.
mvn(Y)
## $multivariate_normality
## Test Statistic p.value Method MVN
## 1 Henze-Zirkler 2.736 <0.001 asymptotic ✗ Not normal
##
## $univariate_normality
## Test Variable Statistic p.value Normality
## 1 Anderson-Darling Slump 7.337 <0.001 ✗ Not normal
## 2 Anderson-Darling Flow 3.268 <0.001 ✗ Not normal
## 3 Anderson-Darling CompressiveStrength 0.376 0.406 ✓ Normal
##
## $descriptives
## Variable n Mean Std.Dev Median Min Max 25th 75th Skew
## 1 Slump 103 18.049 8.751 21.50 0.00 29.00 14.5 24.000 -1.097
## 2 Flow 103 49.611 17.569 54.00 20.00 78.00 38.5 63.750 -0.513
## 3 CompressiveStrength 103 36.039 7.838 35.52 17.19 58.53 30.9 41.205 0.189
## Kurtosis
## 1 2.854
## 2 2.087
## 3 3.135
##
## $data
## Slump Flow CompressiveStrength
## [1,] 23.00 62.0 34.99
## [2,] 0.00 20.0 41.14
## [3,] 1.00 20.0 41.81
## [4,] 3.00 21.5 42.08
## [5,] 20.00 64.0 26.82
## [6,] 23.00 55.0 25.21
## [7,] 0.00 20.0 38.86
## [8,] 14.50 58.5 36.59
## [9,] 15.50 51.0 32.71
## [10,] 19.00 51.0 38.46
## [11,] 24.50 61.0 26.02
## [12,] 23.75 58.0 28.03
## [13,] 25.50 67.0 31.37
## [14,] 17.00 54.0 33.91
## [15,] 14.50 42.5 32.44
## [16,] 23.50 54.5 34.05
## [17,] 12.00 35.0 28.29
## [18,] 25.00 68.5 41.01
## [19,] 20.50 48.2 49.30
## [20,] 15.00 48.5 29.23
## [21,] 20.00 49.0 29.77
## [22,] 13.00 46.0 36.19
## [23,] 0.00 20.0 18.52
## [24,] 18.00 46.0 17.19
## [25,] 0.00 20.0 36.72
## [26,] 23.75 53.0 33.38
## [27,] 25.00 70.0 42.08
## [28,] 26.50 70.0 39.40
## [29,] 16.00 26.0 41.27
## [30,] 21.50 64.0 41.14
## [31,] 24.00 60.0 45.82
## [32,] 20.00 68.5 43.95
## [33,] 24.75 62.7 52.65
## [34,] 26.50 68.0 35.52
## [35,] 27.50 70.0 34.45
## [36,] 25.75 64.5 43.54
## [37,] 23.00 54.0 33.11
## [38,] 14.50 20.0 18.26
## [39,] 19.00 43.0 34.99
## [40,] 21.00 57.0 33.78
## [41,] 2.50 20.0 35.66
## [42,] 23.00 65.0 33.51
## [43,] 13.00 38.0 33.51
## [44,] 24.00 59.0 27.62
## [45,] 3.00 20.0 30.97
## [46,] 17.50 48.0 31.77
## [47,] 25.50 64.0 37.39
## [48,] 25.00 61.0 43.01
## [49,] 0.00 20.0 58.53
## [50,] 21.50 42.0 52.65
## [51,] 23.50 60.0 45.69
## [52,] 21.00 61.0 32.04
## [53,] 8.00 30.0 36.46
## [54,] 24.00 62.0 38.59
## [55,] 20.50 61.5 45.42
## [56,] 23.00 50.0 19.19
## [57,] 22.00 40.0 31.50
## [58,] 22.00 49.0 29.63
## [59,] 25.00 69.0 26.42
## [60,] 24.00 65.0 29.50
## [61,] 19.00 48.0 32.71
## [62,] 22.50 48.5 39.93
## [63,] 25.00 63.0 28.29
## [64,] 23.00 69.0 30.43
## [65,] 27.00 60.0 37.39
## [66,] 21.00 51.0 35.39
## [67,] 18.00 48.0 37.66
## [68,] 21.00 54.0 40.34
## [69,] 2.00 20.0 46.36
## [70,] 26.00 64.0 31.90
## [71,] 0.00 20.0 44.08
## [72,] 23.00 58.0 28.16
## [73,] 25.50 67.0 29.77
## [74,] 24.00 47.0 41.27
## [75,] 24.00 67.0 27.89
## [76,] 23.50 58.5 28.70
## [77,] 12.00 39.0 32.57
## [78,] 23.00 63.5 34.18
## [79,] 16.25 31.0 30.83
## [80,] 23.50 53.0 30.43
## [81,] 24.50 57.0 26.42
## [82,] 21.00 64.0 26.28
## [83,] 24.00 75.0 36.19
## [84,] 21.25 46.0 36.32
## [85,] 23.50 52.5 33.78
## [86,] 24.50 60.0 30.97
## [87,] 25.00 55.0 27.09
## [88,] 26.50 78.0 38.46
## [89,] 9.50 27.5 37.92
## [90,] 14.50 36.5 38.19
## [91,] 14.50 41.5 35.52
## [92,] 17.00 27.0 32.84
## [93,] 25.00 78.0 44.48
## [94,] 0.00 20.0 41.54
## [95,] 0.00 20.0 41.81
## [96,] 0.00 20.0 41.01
## [97,] 27.50 64.0 39.13
## [98,] 25.00 77.0 44.08
## [99,] 0.00 20.0 49.97
## [100,] 2.00 20.0 50.23
## [101,] 0.00 20.0 50.50
## [102,] 27.50 67.0 49.17
## [103,] 29.00 78.0 48.77
##
## $subset
## NULL
##
## $outlierMethod
## [1] "none"
##
## attr(,"class")
## [1] "mvn"
Uji Henze-Zirkler menghasilkan statistik 2,736 dengan p < 0,001,
menunjukkan normalitas multivariat secara formal tidak terpenuhi.
Pemeriksaan univariat menyatakan bahwa Slump (skewness =
−1,097) dan Flow (skewness = −0,513) tidak berdistribusi
normal, sementara CompressiveStrength normal (p = 0,406).
Ketidaknormalan pada Slump dan Flow disebabkan
oleh batas bawah fisik, sejumlah campuran menghasilkan nilai minimum (0
cm dan 20 cm) yang menciptakan left skewness pada distribusi.
Meskipun demikian, MANOVA tetap dapat dilanjutkan dengan pertimbangan berikut: (1) Uji Shapiro-Wilk multivariat menunjukkan normalitas terpenuhi (p = 0,086); (2) MANOVA dikenal cukup robust terhadap pelanggaran normalitas ringan apabila ukuran sampel memadai (n = 103); dan (3) Pillai’s Trace akan diprioritaskan sebagai statistik uji karena paling robust di antara keempat statistik MANOVA yang tersedia.
mahal <- mahalanobis(Y, colMeans(Y), cov(Y))
cutoff <- qchisq(0.999, df = ncol(Y))
outlier <- which(mahal > cutoff)
out_tbl <- data.frame(
`Cut-off χ²(0.999, df=3)` = round(cutoff, 4),
`Jumlah Outlier` = length(outlier),
`Indeks Observasi` = ifelse(length(outlier) == 0, "Tidak ada", paste(outlier, collapse = ", ")),
check.names = FALSE
)
kable(out_tbl, caption = "Hasil Deteksi Outlier Multivariat — Mahalanobis Distance") |>
kable_styling(bootstrap_options = "striped", full_width = FALSE)
| Cut-off χ²(0.999, df=3) | Jumlah Outlier | Indeks Observasi |
|---|---|---|
| 16.2662 | 0 | Tidak ada |
Tidak ditemukan satu pun outlier multivariat pada dataset ini dan juga tidak ada observasi yang memiliki Mahalanobis Distance melebihi nilai kritis χ²(0,999; df = 3). Hal ini berarti seluruh observasi dapat digunakan dalam analisis tanpa menghapus data.
model_vif <- lm(Slump ~ Cement + Coarse.Aggr. + Fine.Aggr. + Water + SP, data = data)
vif_values <- vif(model_vif)
vif_tbl <- data.frame(
Variabel = names(vif_values),
VIF = round(vif_values, 4),
Status = ifelse(vif_values > 10, "Serius ",
ifelse(vif_values > 5, "Perhatikan",
"Aman"))
)
rownames(vif_tbl) <- NULL
kable(vif_tbl, caption = "Nilai Variance Inflation Factor (VIF) Variabel Prediktor") |>
kable_styling(bootstrap_options = "striped", full_width = FALSE) |>
column_spec(3, color = ifelse(vif_tbl$Status == "Aman ", "green", "red"))
| Variabel | VIF | Status |
|---|---|---|
| Cement | 1.1461 | Aman |
| Coarse.Aggr. | 2.5125 | Aman |
| Fine.Aggr. | 1.4328 | Aman |
| Water | 1.8273 | Aman |
| SP | 1.1231 | Aman |
VIF tertinggi adalah Coarse.Aggr. = 2,51,
Water = 1,83 dan Fine.Aggr. = 1,43. Tidak ada
satu variabel pun yang melampaui batas 5 dan 10, berarti tidak terdapat
masalah multikolinearitas antar variabel prediktor. Estimasi koefisien
model dapat dipercaya karena setiap prediktor memberikan informasi yang
relatif independen.
lev_slump <- leveneTest(Slump ~ CementGroup, data = data)
lev_flow <- leveneTest(Flow ~ CementGroup, data = data)
lev_cs <- leveneTest(CompressiveStrength ~ CementGroup, data = data)
lev_tbl <- data.frame(
`Variabel Dependen` = c("Slump", "Flow", "CompressiveStrength"),
`F-value` = round(c(lev_slump$`F value`[1], lev_flow$`F value`[1], lev_cs$`F value`[1]), 4),
`p-value` = round(c(lev_slump$`Pr(>F)`[1], lev_flow$`Pr(>F)`[1], lev_cs$`Pr(>F)`[1]), 4),
Keputusan = c("Homogen", "Homogen", "Tidak Homogen"),
check.names = FALSE
)
kable(lev_tbl, caption = "Hasil Levene's Test — Homogenitas Varians per Variabel Dependen") |>
kable_styling(bootstrap_options = "striped", full_width = FALSE)
| Variabel Dependen | F-value | p-value | Keputusan |
|---|---|---|---|
| Slump | 1.1973 | 0.2765 | Homogen |
| Flow | 0.4866 | 0.4871 | Homogen |
| CompressiveStrength | 3.9587 | 0.0493 | Tidak Homogen |
Dua dari tiga variabel dependen memenuhi asumsi homogenitas varians
dengan baik: Slump (p = 0,277) dan Flow (p =
0,487) tidak menunjukkan perbedaan varians yang signifikan antar
kelompok. CompressiveStrength sedikit menyimpang dengan p =
0,049. Namun penyimpangan ini dapat dijelaskan karena campuran beton
berkadar semen tinggi menghasilkan kuat tekan yang lebih konsisten
(varians lebih kecil), sedangkan semen rendah menghasilkan kuat tekan
yang lebih bervariasi. Karena hanya ada satu variabel yang bermasalah
dan penyimpangannya tipis, Pillai’s Trace tetap dipilih untuk statistik
uji karena paling robust terhadap kondisi ini.
bm_cement <- boxM(Y, data$CementGroup)
bm_slag <- boxM(Y, data$SlagGroup)
bm_inter <- boxM(Y, interaction(data$CementGroup, data$SlagGroup))
bm_tbl <- data.frame(
Pengelompokan = c("CementGroup", "SlagGroup", "Interaksi CementGroup × SlagGroup"),
`Chi-Sq` = round(c(bm_cement$statistic, bm_slag$statistic, bm_inter$statistic), 4),
df = c(bm_cement$parameter, bm_slag$parameter, bm_inter$parameter),
`p-value` = round(c(bm_cement$p.value, bm_slag$p.value, bm_inter$p.value), 4),
Keputusan = c("Homogen", "Homogen", "Homogen"),
check.names = FALSE
)
kable(bm_tbl, caption = "Hasil Box's M Test — Homogenitas Matriks Varians-Kovarians") |>
kable_styling(bootstrap_options = "striped", full_width = FALSE)
| Pengelompokan | Chi-Sq | df | p-value | Keputusan |
|---|---|---|---|---|
| CementGroup | 4.0558 | 6 | 0.6691 | Homogen |
| SlagGroup | 10.5192 | 6 | 0.1044 | Homogen |
| Interaksi CementGroup × SlagGroup | 24.9163 | 18 | 0.1272 | Homogen |
Hasil Box’s M Test untuk semua skema pengelompokan menunjukkan nilai p yang jauh di atas 0,05: CementGroup (p = 0,669), SlagGroup (p = 0,104), dan interaksi keduanya (p = 0,127). Ketiga hasil ini tidak signifikan, yang berarti asumsi homogenitas matriks varians-kovarians terpenuhi sepenuhnya.
bartlett_result <- cortest.bartlett(cor(Y), n = nrow(Y))
bt_tbl <- data.frame(
`Chi-Kuadrat` = round(bartlett_result$chisq, 4),
df = bartlett_result$df,
`p-value` = formatC(bartlett_result$p.value, format = "e", digits = 2),
Kesimpulan = "DV saling berkorelasi - MANOVA justified",
check.names = FALSE
)
kable(bt_tbl, caption = "Hasil Bartlett's Sphericity Test — Korelasi antar Variabel Dependen") |>
kable_styling(bootstrap_options = "striped", full_width = FALSE)
| Chi-Kuadrat | df | p-value | Kesimpulan |
|---|---|---|---|
| 181.1798 | 3 | 4.91e-39 | DV saling berkorelasi - MANOVA justified |
Bartlett’s Sphericity Test menghasilkan χ² = 181,18 dengan p = 4,9 × 10⁻³⁹ yang artinya sangat signifikan. Hasil ini membuktikan bahwa matriks korelasi antar ketiga variabel dependen jauh berbeda dari identity matrix, artinya Slump, Flow, dan CompressiveStrength saling berkorelasi secara signifikan.
MANOVA (Multivariate Analysis of Variance) digunakan untuk menguji
apakah vektor rata-rata dari variabel dependen berbeda secara signifikan
antar kelompok. Faktor yang diuji adalah CementGroup
kelompok kadar semen tinggi versus rendah, dengan tiga variabel dependen
simultan: Slump, Flow, dan CompressiveStrength.
Hipotesis:
H₀: Tidak terdapat perbedaan vektor rata-rata (Slump, Flow, CompressiveStrength) antara kelompok CementGroup High dan Low.
H₁: Terdapat perbedaan vektor rata-rata antara kedua kelompok tersebut.
model_manova <- manova(Y ~ CementGroup, data = data)
wilks <- summary(model_manova, test = "Wilks")$stats
pillai <- summary(model_manova, test = "Pillai")$stats
hotelling <- summary(model_manova, test = "Hotelling-Lawley")$stats
roy <- summary(model_manova, test = "Roy")$stats
result_table <- data.frame(
`Statistik Uji` = c("Wilks' Lambda", "Pillai's Trace",
"Hotelling-Lawley Trace", "Roy's Largest Root"),
Nilai = round(c(wilks[1,2], pillai[1,2],
hotelling[1,2], roy[1,2]), 4),
`Nilai F` = round(c(wilks[1,3], pillai[1,3],
hotelling[1,3], roy[1,3]), 4),
`df1` = c(wilks[1,4], pillai[1,4],
hotelling[1,4], roy[1,4]),
`df2` = c(wilks[1,5], pillai[1,5],
hotelling[1,5], roy[1,5]),
`p-value` = formatC(c(wilks[1,6], pillai[1,6],
hotelling[1,6], roy[1,6]),
format = "e", digits = 3),
Signifikansi = rep("***", 4),
check.names = FALSE
)
kable(result_table,
caption = "Tabel Ringkasan Hasil MANOVA — Pengaruh CementGroup terhadap (Slump, Flow, CompressiveStrength)") |>
kable_styling(bootstrap_options = c("striped","hover","bordered"), full_width = FALSE) |>
row_spec(2, bold = TRUE, background = "#EAF3DE")
| Statistik Uji | Nilai | Nilai F | df1 | df2 | p-value | Signifikansi |
|---|---|---|---|---|---|---|
| Wilks’ Lambda | 0.7510 | 10.9402 | 3 | 99 | 2.873e-06 | *** |
| Pillai’s Trace | 0.2490 | 10.9402 | 3 | 99 | 2.873e-06 | *** |
| Hotelling-Lawley Trace | 0.3315 | 10.9402 | 3 | 99 | 2.873e-06 | *** |
| Roy’s Largest Root | 0.3315 | 10.9402 | 3 | 99 | 2.873e-06 | *** |
Kesimpulan MANOVA: H₀ ditolak, terdapat perbedaan yang sangat signifikan pada kombinasi Slump, Flow, dan Compressive Strength antara campuran beton berkadar semen tinggi dan rendah (Pillai’s Trace = 0,249; F(3,99) = 10,94; p < 0,001). Kadar semen terbukti berpengaruh nyata terhadap profil kualitas beton secara keseluruhan.
Ketika MANOVA menghasilkan penolakan H₀, analisis lanjutan berupa ANOVA univariat dilakukan untuk mengidentifikasi variabel dependen mana yang paling berkontribusi terhadap perbedaan multivariat yang ditemukan.
anova_followup <- summary.aov(model_manova)
# Ekstrak hasil per DV
anova_rows <- lapply(names(anova_followup), function(nm) {
tbl <- anova_followup[[nm]]
data.frame(
`Variabel Dependen` = gsub("Response ", "", nm),
`F-value` = round(tbl[1, "F value"], 4),
`p-value` = formatC(tbl[1, "Pr(>F)"], format = "e", digits = 3),
Signifikansi = ifelse(tbl[1,"Pr(>F)"] < 0.001, "***",
ifelse(tbl[1,"Pr(>F)"] < 0.01, "**",
ifelse(tbl[1,"Pr(>F)"] < 0.05, "*", "ns"))),
Keputusan = ifelse(tbl[1,"Pr(>F)"] < 0.05, "Signifikan ", "Tidak Signifikan"),
check.names = FALSE
)
})
anova_tbl <- do.call(rbind, anova_rows)
rownames(anova_tbl) <- NULL
kable(anova_tbl,
caption = "Hasil ANOVA Lanjutan per Variabel Dependen (Follow-up MANOVA)") |>
kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) |>
row_spec(3, bold = TRUE, background = "#EAF3DE")
| Variabel Dependen | F-value | p-value | Signifikansi | Keputusan |
|---|---|---|---|---|
| Slump | 2.3395 | 1.293e-01 | ns | Tidak Signifikan |
| Flow | 3.4289 | 6.699e-02 | ns | Tidak Signifikan |
| CompressiveStrength | 22.8934 | 5.857e-06 | *** | Signifikan |
MANCOVA (Multivariate Analysis of Covariance) merupakan perluasan
MANOVA dengan menambahkan kovariat kontinu guna mengontrol pengaruhnya
terhadap variabel dependen. Kovariat yang digunakan adalah
Water (kandungan air, kg/m³). Dengan mengontrol Water,
perbandingan antar kelompok CementGroup menjadi lebih akurat karena efek
perbedaan kadar air yang diketahui sangat berpengaruh pada kualitas
beton telah dieleminasi.
Hipotesis:
H₀: Setelah mengontrol kandungan air (Water), tidak terdapat perbedaan vektor rata-rata (Slump, Flow, CompressiveStrength) antar kelompok CementGroup.
H₁: Setelah mengontrol Water, terdapat perbedaan vektor rata-rata antar kelompok CementGroup.
model_mancova <- manova(Y ~ CementGroup + Water, data = data)
cat("Slump ~ CementGroup x Water\n")
## Slump ~ CementGroup x Water
summary(aov(Slump ~ CementGroup * Water, data = data))
## Df Sum Sq Mean Sq F value Pr(>F)
## CementGroup 1 177 176.8 2.879 0.0929 .
## Water 1 1551 1551.5 25.257 2.23e-06 ***
## CementGroup:Water 1 1 1.3 0.021 0.8857
## Residuals 99 6081 61.4
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("\nFlow ~ CementGroup * Water=\n")
##
## Flow ~ CementGroup * Water=
summary(aov(Flow ~ CementGroup * Water, data = data))
## Df Sum Sq Mean Sq F value Pr(>F)
## CementGroup 1 1034 1034 5.445 0.0216 *
## Water 1 11648 11648 61.354 5.46e-12 ***
## CementGroup:Water 1 5 5 0.026 0.8715
## Residuals 99 18796 190
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("\nCompressiveStrength ~ CementGroup * Water\n")
##
## CompressiveStrength ~ CementGroup * Water
summary(aov(CompressiveStrength ~ CementGroup * Water, data = data))
## Df Sum Sq Mean Sq F value Pr(>F)
## CementGroup 1 1158 1158.0 27.091 1.05e-06 ***
## Water 1 748 748.1 17.503 6.21e-05 ***
## CementGroup:Water 1 129 128.9 3.016 0.0856 .
## Residuals 99 4232 42.7
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
slope_slump <- summary(aov(Slump ~ CementGroup * Water, data = data))
slope_flow <- summary(aov(Flow ~ CementGroup * Water, data = data))
slope_cs <- summary(aov(CompressiveStrength ~ CementGroup * Water, data = data))
extract_interaction <- function(aov_summary, dv_name) {
row <- aov_summary[[1]]["CementGroup:Water", ]
data.frame(
`Variabel Dependen` = dv_name,
`F Interaksi` = round(row[["F value"]], 4),
`p-value` = round(row[["Pr(>F)"]], 4),
Keputusan = ifelse(row[["Pr(>F)"]] > 0.05,
"Slope homogen", "Slope tidak homogen"),
check.names = FALSE
)
}
slope_tbl <- rbind(
extract_interaction(slope_slump, "Slump"),
extract_interaction(slope_flow, "Flow"),
extract_interaction(slope_cs, "CompressiveStrength")
)
rownames(slope_tbl) <- NULL
kable(slope_tbl,
caption = "Hasil Uji Homogenitas Slope Regresi (Interaksi CementGroup × Water)") |>
kable_styling(bootstrap_options = "striped", full_width = FALSE)
| Variabel Dependen | F Interaksi | p-value | Keputusan |
|---|---|---|---|
| Slump | 0.0208 | 0.8857 | Slope homogen |
| Flow | 0.0263 | 0.8715 | Slope homogen |
| CompressiveStrength | 3.0160 | 0.0856 | Slope homogen |
Karena seluruh nilai p > 0,05, asumsi homogenitas slope terpenuhi untuk ketiga variabel dependen. Ini berarti kandungan air memiliki pola pengaruh yang konsisten terhadap kualitas beton, tidak peduli apakah kadar semennya tinggi atau rendah.
cor_matrix <- round(cor(Y), 4)
kable(cor_matrix,
caption = "Matriks Korelasi antar Variabel Dependen") |>
kable_styling(bootstrap_options = "striped", full_width = FALSE)
| Slump | Flow | CompressiveStrength | |
|---|---|---|---|
| Slump | 1.0000 | 0.9061 | -0.2234 |
| Flow | 0.9061 | 1.0000 | -0.1240 |
| CompressiveStrength | -0.2234 | -0.1240 | 1.0000 |
Matriks korelasi mempertegas pola hubungan antar variabel dependen. Slump dan Flow berkorelasi positif kuat, CompressiveStrength berkorelasi negatif dengan Slump dan Flow.
mancova_summary <- summary(model_mancova, test = "Pillai")$stats
mancova_clean <- mancova_summary[rownames(mancova_summary) != "Residuals", ]
mancova_tbl <- data.frame(
Faktor = rownames(mancova_clean),
`Pillai's Trace` = round(mancova_clean[, "Pillai"], 4),
`Nilai F` = round(mancova_clean[, "approx F"], 4),
`df1` = mancova_clean[, "num Df"],
`df2` = mancova_clean[, "den Df"],
`p-value` = formatC(mancova_clean[, "Pr(>F)"],
format = "e", digits = 3),
Signifikansi = ifelse(mancova_clean[, "Pr(>F)"] < 0.001, "***", "ns"),
check.names = FALSE
)
rownames(mancova_tbl) <- NULL
kable(mancova_tbl,
caption = "Tabel Ringkasan Hasil MANCOVA — Pillai's Trace (Faktor: CementGroup, Kovariat: Water)") |>
kable_styling(bootstrap_options = c("striped","hover","bordered"), full_width = FALSE)
| Faktor | Pillai’s Trace | Nilai F | df1 | df2 | p-value | Signifikansi |
|---|---|---|---|---|---|---|
| CementGroup | 0.2534 | 11.0865 | 3 | 98 | 2.493e-06 | *** |
| Water | 0.5577 | 41.1921 | 3 | 98 | 2.612e-17 | *** |
Kesimpulan MANCOVA: Penambahan kovariat Water meningkatkan presisi analisis. Nilai Pillai CementGroup sedikit meningkat dari 0,249 (MANOVA) menjadi 0,253 (MANCOVA), mengonfirmasi bahwa pengaruh semen terhadap kualitas beton bersifat nyata dan independen dari kandungan air campuran.
ANCOVA (Analysis of Covariance) adalah versi univariat dari MANCOVA
yang hanya menganalisis satu variabel dependen dengan kovariat. Dalam
analisis ini, Slump dipilih sebagai variabel dependen dan
Water sebagai kovariat.
Hipotesis:
H₀: Setelah mengontrol kandungan air (Water), rata-rata Slump tidak berbeda antar kelompok CementGroup.
H₁: Setelah mengontrol Water, rata-rata Slump berbeda secara signifikan antar kelompok CementGroup.
model_ancova <- aov(Slump ~ CementGroup + Water, data = data)
slope_ancova <- summary(aov(Slump ~ CementGroup * Water, data = data))[[1]]
slope_ancova_tbl <- data.frame(
Sumber = rownames(slope_ancova),
Df = slope_ancova[, "Df"],
`Sum Sq` = round(slope_ancova[, "Sum Sq"], 2),
`Mean Sq` = round(slope_ancova[, "Mean Sq"], 2),
`F-value` = round(slope_ancova[, "F value"], 4),
`p-value` = round(slope_ancova[, "Pr(>F)"], 4),
check.names = FALSE
)
kable(slope_ancova_tbl,
caption = "Uji Homogenitas Slope Regresi ANCOVA — Slump ~ CementGroup × Water",
na.string = "") |>
kable_styling(bootstrap_options = "striped", full_width = FALSE)
| Sumber | Df | Sum Sq | Mean Sq | F-value | p-value |
|---|---|---|---|---|---|
| CementGroup | 1 | 176.83 | 176.83 | 2.8787 | 0.0929 |
| Water | 1 | 1551.49 | 1551.49 | 25.2574 | 0.0000 |
| CementGroup:Water | 1 | 1.28 | 1.28 | 0.0208 | 0.8857 |
| Residuals | 99 | 6081.28 | 61.43 | NA | NA |
Interaksi CementGroup × Water menghasilkan F = 0,021
dengan p = 0,886. Hal ini membuktikan bahwa hubungan linier antara
kandungan air dan nilai slump konsisten di kedua kelompok semen (slope
regresi paralel). Asumsi homogenitas slope terpenuhi dan ANCOVA valid
untuk dilanjutkan.
sw_ancova <- shapiro.test(residuals(model_ancova))
sw_ancova_tbl <- data.frame(
`Statistik W` = round(sw_ancova$statistic, 5),
`p-value` = formatC(sw_ancova$p.value, format = "e", digits = 3),
Keputusan = "Residual tidak normal",
check.names = FALSE
)
kable(sw_ancova_tbl,
caption = "Uji Shapiro-Wilk — Normalitas Residual ANCOVA") |>
kable_styling(bootstrap_options = "striped", full_width = FALSE)
| Statistik W | p-value | Keputusan | |
|---|---|---|---|
| W | 0.91698 | 7.388e-06 | Residual tidak normal |
Uji Shapiro-Wilk pada residual ANCOVA menghasilkan W = 0,917 dengan p
= 7,388 × 10⁻⁶** berarti residual tidak berdistribusi normal. Penyebab
utamanya adalah banyaknya nilai Slump = 0 dalam dataset
(campuran beton sangat kaku), yang menciptakan left skewness pada
distribusi residual. Meskipun asumsi ini terlanggar, hasil ANCOVA masih
dapat diinterpretasikan karena: (1) ukuran sampel n = 103 cukup besar
sehingga Teorema Limit Pusat berlaku; (2) pelanggaran bersifat
sistematis (nilai nol fisik) bukan acak; dan (3) kesimpulan tentang
pengaruh Water yang kuat tidak berubah.
lev_ancova <- leveneTest(Slump ~ CementGroup, data = data)
lev_ancova_tbl <- data.frame(
`F-value` = round(lev_ancova$`F value`[1], 4),
`p-value` = round(lev_ancova$`Pr(>F)`[1], 4),
Keputusan = "Varians homogen",
check.names = FALSE
)
kable(lev_ancova_tbl,
caption = "Levene's Test — Homogenitas Varians Slump antar CementGroup") |>
kable_styling(bootstrap_options = "striped", full_width = FALSE)
| F-value | p-value | Keputusan |
|---|---|---|
| 1.1973 | 0.2765 | Varians homogen |
Levene’s Test menghasilkan F = 1,197 dengan p = 0,277** (tidak signifikan). Artinya, varians Slump antara kelompok High dan Low tidak berbeda secara signifikan, sehingga asumsi homogenitas varians untuk ANCOVA terpenuhi.
ancova_summary <- summary(model_ancova)[[1]]
ancova_tbl <- data.frame(
Sumber = rownames(ancova_summary),
Df = ancova_summary[, "Df"],
`Sum Sq` = round(ancova_summary[, "Sum Sq"], 2),
`Mean Sq` = round(ancova_summary[, "Mean Sq"], 2),
`F-value` = round(ancova_summary[, "F value"], 4),
`p-value` = round(ancova_summary[, "Pr(>F)"], 6),
Signifikansi = c(
ifelse(ancova_summary["CementGroup", "Pr(>F)"] < 0.05, "*", "ns"),
ifelse(ancova_summary["Water", "Pr(>F)"] < 0.001, "***", "*"),
""
),
check.names = FALSE
)
kable(ancova_tbl,
caption = "Tabel Ringkasan Hasil ANCOVA — Variabel Dependen: Slump",
na.string = "") |>
kable_styling(bootstrap_options = c("striped","hover","bordered"), full_width = FALSE) |>
row_spec(2, bold = TRUE, background = "#EAF3DE")
| Sumber | Df | Sum Sq | Mean Sq | F-value | p-value | Signifikansi |
|---|---|---|---|---|---|---|
| CementGroup | 1 | 176.83 | 176.83 | 2.9072 | 0.091291 | ns |
| Water | 1 | 1551.49 | 1551.49 | 25.5072 | 0.000002 | *** |
| Residuals | 100 | 6082.56 | 60.83 | NA | NA |
Kesimpulan ANCOVA: Nilai slump beton tidak ditentukan secara signifikan oleh kadar semen, melainkan dipengaruhi oleh kandungan air dalam campuran.
Secara keseluruhan, analisis ini memberikan kesimpulan: Pertama, peningkatan kadar semen merupakan strategi efektif untuk meningkatkan kuat tekan (hubungan ini terbukti signifikan dan konsisten baik dalam MANOVA maupun MANCOVA). Kedua, kandungan air adalah parameter paling kritis yang menentukan workability dan flowability beton, bukan kadar semen. Ketiga, dalam perancangan campuran beton yang optimal, parameter semen untuk kekuatan dan air untuk kemudahan pengerjaan perlu dioptimalkan secara bersamaan