1. Library

library(MVN)        # Uji Multivariate Normality
library(biotools)   # Box's M test
library(car)        # Uji linearitas

2. Load Data

data <- read.csv("collegiate_athlete_injury_dataset.csv", header = TRUE)
str(data)
## 'data.frame':    200 obs. of  17 variables:
##  $ Athlete_ID              : chr  "A001" "A002" "A003" "A004" ...
##  $ Age                     : int  24 21 22 24 20 22 22 24 19 20 ...
##  $ Gender                  : chr  "Female" "Male" "Male" "Female" ...
##  $ Height_cm               : int  195 192 163 192 173 180 179 167 166 162 ...
##  $ Weight_kg               : int  99 65 83 90 79 75 90 64 91 63 ...
##  $ Position                : chr  "Center" "Forward" "Guard" "Guard" ...
##  $ Training_Intensity      : int  2 8 8 1 3 9 5 6 4 2 ...
##  $ Training_Hours_Per_Week : int  13 14 8 13 9 14 13 7 19 8 ...
##  $ Recovery_Days_Per_Week  : int  2 1 2 1 1 3 1 2 2 3 ...
##  $ Match_Count_Per_Week    : int  3 3 1 1 2 4 4 3 3 3 ...
##  $ Rest_Between_Events_Days: int  1 1 3 1 1 1 2 3 3 2 ...
##  $ Fatigue_Score           : int  1 4 6 7 2 6 7 2 2 7 ...
##  $ Performance_Score       : int  99 55 58 82 90 74 97 62 58 62 ...
##  $ Team_Contribution_Score : int  58 63 62 74 51 84 56 70 67 52 ...
##  $ Load_Balance_Score      : int  100 83 100 78 83 99 78 100 80 100 ...
##  $ ACL_Risk_Score          : int  4 73 62 51 49 54 84 42 50 35 ...
##  $ Injury_Indicator        : int  0 0 0 0 0 0 1 0 0 0 ...
summary(data)
##   Athlete_ID             Age           Gender            Height_cm    
##  Length:200         Min.   :18.00   Length:200         Min.   :160.0  
##  Class :character   1st Qu.:19.00   Class :character   1st Qu.:171.0  
##  Mode  :character   Median :21.00   Mode  :character   Median :182.5  
##                     Mean   :21.17                      Mean   :180.8  
##                     3rd Qu.:23.00                      3rd Qu.:191.0  
##                     Max.   :24.00                      Max.   :199.0  
##    Weight_kg       Position         Training_Intensity Training_Hours_Per_Week
##  Min.   :55.00   Length:200         Min.   :1.000      Min.   : 5.00          
##  1st Qu.:67.00   Class :character   1st Qu.:3.000      1st Qu.: 7.00          
##  Median :77.50   Mode  :character   Median :5.000      Median :11.00          
##  Mean   :77.47                      Mean   :5.105      Mean   :11.31          
##  3rd Qu.:89.00                      3rd Qu.:7.000      3rd Qu.:15.00          
##  Max.   :99.00                      Max.   :9.000      Max.   :19.00          
##  Recovery_Days_Per_Week Match_Count_Per_Week Rest_Between_Events_Days
##  Min.   :1.000          Min.   :1.000        Min.   :1.000           
##  1st Qu.:1.000          1st Qu.:1.000        1st Qu.:1.000           
##  Median :2.000          Median :2.000        Median :2.000           
##  Mean   :1.985          Mean   :2.385        Mean   :1.975           
##  3rd Qu.:3.000          3rd Qu.:3.000        3rd Qu.:3.000           
##  Max.   :3.000          Max.   :4.000        Max.   :3.000           
##  Fatigue_Score  Performance_Score Team_Contribution_Score Load_Balance_Score
##  Min.   :1.00   Min.   :50.00     Min.   :50.00           Min.   : 62.00    
##  1st Qu.:3.00   1st Qu.:62.00     1st Qu.:60.75           1st Qu.: 89.00    
##  Median :5.00   Median :74.00     Median :72.00           Median : 98.00    
##  Mean   :4.92   Mean   :74.47     Mean   :72.63           Mean   : 93.39    
##  3rd Qu.:7.00   3rd Qu.:86.25     3rd Qu.:85.00           3rd Qu.:100.00    
##  Max.   :9.00   Max.   :99.00     Max.   :99.00           Max.   :100.00    
##  ACL_Risk_Score   Injury_Indicator
##  Min.   :  2.00   Min.   :0.00    
##  1st Qu.: 33.00   1st Qu.:0.00    
##  Median : 45.00   Median :0.00    
##  Mean   : 46.47   Mean   :0.07    
##  3rd Qu.: 60.00   3rd Qu.:0.00    
##  Max.   :100.00   Max.   :1.00

3. Preprocessing

# Hapus missing values
data_clean <- na.omit(data)

# Faktorkan variabel grup (Position sebagai IV)
data_clean$Position <- as.factor(data_clean$Position)

cat("Dimensi data bersih:", nrow(data_clean), "baris,", ncol(data_clean), "kolom\n")
## Dimensi data bersih: 200 baris, 17 kolom
cat("Level Position:", levels(data_clean$Position), "\n")
## Level Position: Center Forward Guard

4. Uji Asumsi

4.1 Uji Multivariate Normality (MVN)

DV yang diuji: Load_Balance_Score & ACL_Risk_Score

dv <- data_clean[, c("Load_Balance_Score", "ACL_Risk_Score")]
mvn_result <- MVN::mvn(data = dv)
mvn_result
## $multivariate_normality
##            Test Statistic p.value     Method          MVN
## 1 Henze-Zirkler     6.237  <0.001 asymptotic ✗ Not normal
## 
## $univariate_normality
##               Test           Variable Statistic p.value    Normality
## 1 Anderson-Darling Load_Balance_Score    16.108  <0.001 ✗ Not normal
## 2 Anderson-Darling     ACL_Risk_Score     0.393   0.374     ✓ Normal
## 
## $descriptives
##             Variable   n   Mean Std.Dev Median Min Max 25th 75th   Skew
## 1 Load_Balance_Score 200 93.395   8.660     98  62 100   89  100 -1.346
## 2     ACL_Risk_Score 200 46.470  18.944     45   2 100   33   60  0.205
##   Kurtosis
## 1    4.082
## 2    2.758
## 
## $data
##     Load_Balance_Score ACL_Risk_Score
## 1                  100              4
## 2                   83             73
## 3                  100             62
## 4                   78             51
## 5                   83             49
## 6                   99             54
## 7                   78             84
## 8                  100             42
## 9                   80             50
## 10                 100             35
## 11                  84             35
## 12                  95             57
## 13                  89             55
## 14                  87             72
## 15                  88             74
## 16                  98             47
## 17                 100             61
## 18                  81             75
## 19                 100             60
## 20                  98             26
## 21                 100             53
## 22                  72             71
## 23                  80             69
## 24                  70             81
## 25                  93             65
## 26                 100             29
## 27                  83             47
## 28                  82             67
## 29                  93             50
## 30                  94             44
## 31                 100             62
## 32                 100             35
## 33                  93             46
## 34                 100             35
## 35                 100             44
## 36                  96             43
## 37                 100             43
## 38                  75             74
## 39                 100             30
## 40                  91             77
## 41                  92             67
## 42                  91             48
## 43                 100             49
## 44                  93             36
## 45                  90             56
## 46                 100             42
## 47                 100             28
## 48                 100             45
## 49                  80             66
## 50                 100             33
## 51                  92             46
## 52                  97             70
## 53                 100             33
## 54                  89             52
## 55                  79             36
## 56                  91             45
## 57                 100             29
## 58                 100             47
## 59                 100             28
## 60                 100             20
## 61                  99             44
## 62                  81             52
## 63                  91             39
## 64                  96             53
## 65                 100             40
## 66                 100             60
## 67                  98             12
## 68                  94             30
## 69                  98             16
## 70                  97             68
## 71                 100             37
## 72                  96             47
## 73                  93             33
## 74                  93             17
## 75                  99             29
## 76                 100             22
## 77                 100             25
## 78                 100             60
## 79                  84             50
## 80                 100             32
## 81                  83             58
## 82                 100             50
## 83                 100             33
## 84                  94             25
## 85                  87             72
## 86                 100             37
## 87                 100             23
## 88                  95             27
## 89                 100             32
## 90                 100             41
## 91                  91             49
## 92                 100             38
## 93                  90             74
## 94                  84             53
## 95                  66             81
## 96                  86             55
## 97                  78             91
## 98                  87             65
## 99                  77             70
## 100                 94             41
## 101                100             63
## 102                 84             48
## 103                100             30
## 104                 99             57
## 105                100             56
## 106                100             41
## 107                 78             93
## 108                100             58
## 109                100             38
## 110                 95             28
## 111                 92             61
## 112                100             13
## 113                 91             42
## 114                100             35
## 115                100             28
## 116                 90             45
## 117                 86             55
## 118                 89             50
## 119                 98             59
## 120                 62            100
## 121                100             19
## 122                 82             66
## 123                100             24
## 124                 97             54
## 125                 90             18
## 126                100             61
## 127                100             36
## 128                100             41
## 129                100             72
## 130                 69             62
## 131                 89             33
## 132                100             47
## 133                 89             42
## 134                 98              7
## 135                 88             81
## 136                 98             77
## 137                100             42
## 138                 93             47
## 139                 79             61
## 140                100             20
## 141                100             61
## 142                100             31
## 143                100             12
## 144                100             23
## 145                 69             79
## 146                 91             41
## 147                100             44
## 148                 99             48
## 149                 95             45
## 150                 98             35
## 151                100             40
## 152                100             18
## 153                100             32
## 154                 97             42
## 155                100             27
## 156                 71             33
## 157                100             42
## 158                100              9
## 159                100             69
## 160                 94             20
## 161                 94             69
## 162                100             49
## 163                100             52
## 164                 84             36
## 165                100             60
## 166                100             49
## 167                 90             47
## 168                 96             43
## 169                 78             66
## 170                100              2
## 171                 88             70
## 172                 91             76
## 173                100              9
## 174                100             40
## 175                100             17
## 176                100             40
## 177                100             52
## 178                100             31
## 179                 88             64
## 180                 98             43
## 181                100             29
## 182                100             38
## 183                100             67
## 184                100             38
## 185                100             39
## 186                 88             24
## 187                 91             44
## 188                 70             76
## 189                 79             58
## 190                100             28
## 191                 74             94
## 192                 79             79
## 193                 94             30
## 194                 95             40
## 195                 87             42
## 196                100             39
## 197                100             56
## 198                100             25
## 199                 97             61
## 200                100             23
## 
## $subset
## NULL
## 
## $outlierMethod
## [1] "none"
## 
## attr(,"class")
## [1] "mvn"

Interpretasi: Jika nilai p > 0.05 pada uji Henze-Zirkler, asumsi normalitas multivariat terpenuhi.


4.2 Uji Dependensi antar DV (Korelasi)

cor_dv <- cor(dv)
print(cor_dv)
##                    Load_Balance_Score ACL_Risk_Score
## Load_Balance_Score          1.0000000     -0.5682654
## ACL_Risk_Score             -0.5682654      1.0000000

Interpretasi: DV harus saling berkorelasi (tidak independen total) agar MANOVA bermakna. Nilai korelasi sedang (0.2–0.8) adalah ideal.


4.3 Uji Homogenitas Matriks Kovarians (Box’s M)

boxM_result <- boxM(dv, data_clean$Position)
print(boxM_result)
## 
##  Box's M-test for Homogeneity of Covariance Matrices
## 
## data:  dv
## Chi-Sq (approx.) = 4.2488, df = 6, p-value = 0.6431

Interpretasi: Jika p > 0.05, asumsi homogenitas matriks kovarians terpenuhi (tidak ada perbedaan signifikan antar grup).


4.4 Uji Linearitas Kovariat dengan DV

Kovariat: Training_Hours_Per_Week & Training_Intensity
DV: Load_Balance_Score & ACL_Risk_Score

Uji linearitas dilakukan hanya untuk DV yang akan dimasukkan dalam MANCOVA.

par(mfrow = c(2, 2))

plot(data_clean$Training_Hours_Per_Week, data_clean$Load_Balance_Score,
     main = "Training_Hours vs Load_Balance",
     xlab = "Training Hours Per Week", ylab = "Load Balance Score",
     pch = 19, col = "steelblue")
abline(lm(Load_Balance_Score ~ Training_Hours_Per_Week, data = data_clean),
       col = "red", lwd = 2)

plot(data_clean$Training_Intensity, data_clean$Load_Balance_Score,
     main = "Training_Intensity vs Load_Balance",
     xlab = "Training Intensity", ylab = "Load Balance Score",
     pch = 19, col = "steelblue")
abline(lm(Load_Balance_Score ~ Training_Intensity, data = data_clean),
       col = "red", lwd = 2)

plot(data_clean$Training_Hours_Per_Week, data_clean$ACL_Risk_Score,
     main = "Training_Hours vs ACL_Risk",
     xlab = "Training Hours Per Week", ylab = "ACL Risk Score",
     pch = 19, col = "darkorange")
abline(lm(ACL_Risk_Score ~ Training_Hours_Per_Week, data = data_clean),
       col = "red", lwd = 2)

plot(data_clean$Training_Intensity, data_clean$ACL_Risk_Score,
     main = "Training_Intensity vs ACL_Risk",
     xlab = "Training Intensity", ylab = "ACL Risk Score",
     pch = 19, col = "darkorange")
abline(lm(ACL_Risk_Score ~ Training_Intensity, data = data_clean),
       col = "red", lwd = 2)

par(mfrow = c(1, 1))
# Uji signifikansi linear: kovariat ~ DV
cat("Uji Linear: Training_Hours_Per_Week\n")
## Uji Linear: Training_Hours_Per_Week
summary(lm(Load_Balance_Score ~ Training_Hours_Per_Week, data = data_clean))
## 
## Call:
## lm(formula = Load_Balance_Score ~ Training_Hours_Per_Week, data = data_clean)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -23.726  -2.969   1.301   5.281  12.278 
## 
## Coefficients:
##                         Estimate Std. Error t value Pr(>|t|)    
## (Intercept)             104.6861     1.4477  72.314  < 2e-16 ***
## Training_Hours_Per_Week  -0.9979     0.1191  -8.375 9.98e-15 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 7.461 on 198 degrees of freedom
## Multiple R-squared:  0.2616, Adjusted R-squared:  0.2579 
## F-statistic: 70.15 on 1 and 198 DF,  p-value: 9.977e-15
summary(lm(ACL_Risk_Score    ~ Training_Hours_Per_Week, data = data_clean))
## 
## Call:
## lm(formula = ACL_Risk_Score ~ Training_Hours_Per_Week, data = data_clean)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -43.972 -12.875  -1.625  13.479  46.811 
## 
## Coefficients:
##                         Estimate Std. Error t value Pr(>|t|)    
## (Intercept)              36.3865     3.6039  10.096   <2e-16 ***
## Training_Hours_Per_Week   0.8912     0.2966   3.005    0.003 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 18.57 on 198 degrees of freedom
## Multiple R-squared:  0.0436, Adjusted R-squared:  0.03877 
## F-statistic: 9.027 on 1 and 198 DF,  p-value: 0.003003
cat("\n=== Uji Linear: Training_Intensity ===\n")
## 
## === Uji Linear: Training_Intensity ===
summary(lm(Load_Balance_Score ~ Training_Intensity, data = data_clean))
## 
## Call:
## lm(formula = Load_Balance_Score ~ Training_Intensity, data = data_clean)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -30.868  -4.414   4.404   6.404   7.314 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## (Intercept)         94.3245     1.3972   67.51   <2e-16 ***
## Training_Intensity  -0.1821     0.2459   -0.74     0.46    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 8.67 on 198 degrees of freedom
## Multiple R-squared:  0.002761,   Adjusted R-squared:  -0.002276 
## F-statistic: 0.5481 on 1 and 198 DF,  p-value: 0.46
summary(lm(ACL_Risk_Score    ~ Training_Intensity, data = data_clean))
## 
## Call:
## lm(formula = ACL_Risk_Score ~ Training_Intensity, data = data_clean)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -37.414 -11.014  -0.694   9.330  45.586 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## (Intercept)         32.4623     2.8530  11.378  < 2e-16 ***
## Training_Intensity   2.7439     0.5022   5.464 1.39e-07 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 17.7 on 198 degrees of freedom
## Multiple R-squared:  0.131,  Adjusted R-squared:  0.1266 
## F-statistic: 29.85 on 1 and 198 DF,  p-value: 1.389e-07

Catatan: Berdasarkan hasil uji linearitas, kovariat Training_Hours_Per_Week dan Training_Intensity digunakan hanya untuk DV Load_Balance_Score dan ACL_Risk_Score karena keduanya memiliki hubungan linear yang signifikan dengan kedua DV tersebut.


4.5 Uji Homogenitas Slope Regresi (Tidak Ada Interaksi Kovariat × Grup)

# Jika ada interaksi signifikan, asumsi homogenitas slope dilanggar
cat("Load_Balance_Score\n")
## Load_Balance_Score
summary(aov(Load_Balance_Score ~ Position * Training_Hours_Per_Week, data = data_clean))
##                                   Df Sum Sq Mean Sq F value   Pr(>F)    
## Position                           2    217     109   1.924    0.149    
## Training_Hours_Per_Week            1   3734    3734  66.186 4.82e-14 ***
## Position:Training_Hours_Per_Week   2     32      16   0.279    0.757    
## Residuals                        194  10944      56                     
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
summary(aov(Load_Balance_Score ~ Position * Training_Intensity,      data = data_clean))
##                              Df Sum Sq Mean Sq F value Pr(>F)  
## Position                      2    217  108.52   1.472 0.2319  
## Training_Intensity            1     38   38.46   0.522 0.4709  
## Position:Training_Intensity   2    373  186.28   2.527 0.0825 .
## Residuals                   194  14298   73.70                 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("\nACL_Risk_Score\n")
## 
## ACL_Risk_Score
summary(aov(ACL_Risk_Score ~ Position * Training_Hours_Per_Week, data = data_clean))
##                                   Df Sum Sq Mean Sq F value  Pr(>F)   
## Position                           2   1702   851.1   2.492 0.08538 . 
## Training_Hours_Per_Week            1   2565  2565.0   7.510 0.00671 **
## Position:Training_Hours_Per_Week   2    892   446.2   1.306 0.27314   
## Residuals                        194  66256   341.5                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
summary(aov(ACL_Risk_Score ~ Position * Training_Intensity,      data = data_clean))
##                              Df Sum Sq Mean Sq F value   Pr(>F)    
## Position                      2   1702     851   2.786   0.0642 .  
## Training_Intensity            1   9445    9445  30.913 8.85e-08 ***
## Position:Training_Intensity   2    991     496   1.622   0.2002    
## Residuals                   194  59277     306                     
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Interpretasi: Interaksi Position × Kovariat harus tidak signifikan (p > 0.05) agar asumsi homogenitas slope terpenuhi.


5. Model MANOVA (Tanpa Kovariat)

model_manova <- manova(
  cbind(Load_Balance_Score, ACL_Risk_Score) ~ Position,
  data = data_clean
)

summary(model_manova, test = "Pillai")
##            Df   Pillai approx F num Df den Df Pr(>F)
## Position    2 0.025473   1.2707      4    394 0.2809
## Residuals 197
# Hasil univariat untuk setiap DV
summary.aov(model_manova)
##  Response Load_Balance_Score :
##              Df Sum Sq Mean Sq F value Pr(>F)
## Position      2    217 108.520  1.4534 0.2363
## Residuals   197  14709  74.664               
## 
##  Response ACL_Risk_Score :
##              Df Sum Sq Mean Sq F value  Pr(>F)  
## Position      2   1702  851.14  2.4052 0.09289 .
## Residuals   197  69714  353.88                  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

6. Visualisasi Manova (Tanpa Kovariat)

library(ggplot2)

ggplot(data_clean, aes(x = Position, y = Load_Balance_Score, fill = Position)) +
  geom_boxplot() +
  theme_minimal() +
  labs(title = "MANOVA: Load Balance Score per Position")

ggplot(data_clean, aes(x = Position, y = ACL_Risk_Score, fill = Position)) +
  geom_boxplot() +
  theme_minimal() +
  labs(title = "MANOVA: ACL Risk Score per Position")


7. Model MANCOVA (Dengan Kovariat)

Kovariat: Training_Hours_Per_Week + Training_Intensity

model_mancova <- manova(
  cbind(Load_Balance_Score, ACL_Risk_Score) ~ Position +
    Training_Hours_Per_Week + Training_Intensity,
  data = data_clean
)

summary(model_mancova, test = "Pillai")
##                          Df   Pillai approx F num Df den Df    Pr(>F)    
## Position                  2 0.031431    1.557      4    390    0.1852    
## Training_Hours_Per_Week   1 0.266075   35.166      2    194 9.295e-14 ***
## Training_Intensity        1 0.170478   19.935      2    194 1.338e-08 ***
## Residuals               195                                              
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Hasil univariat untuk setiap DV (setelah dikontrol kovariat)
summary.aov(model_mancova)
##  Response Load_Balance_Score :
##                          Df  Sum Sq Mean Sq F value    Pr(>F)    
## Position                  2   217.0   108.5  1.9368    0.1469    
## Training_Hours_Per_Week   1  3733.6  3733.6 66.6360 3.981e-14 ***
## Training_Intensity        1    49.4    49.4  0.8811    0.3491    
## Residuals               195 10925.8    56.0                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##  Response ACL_Risk_Score :
##                          Df Sum Sq Mean Sq F value    Pr(>F)    
## Position                  2   1702   851.1  2.8831  0.058352 .  
## Training_Hours_Per_Week   1   2565  2565.0  8.6883  0.003593 ** 
## Training_Intensity        1   9580  9580.5 32.4519 4.451e-08 ***
## Residuals               195  57568   295.2                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

8. Visualisasi Mancova (Setelah Kontrol Kovariat)

# Ambil residual (nilai setelah dikontrol kovariat)
model_lb <- lm(Load_Balance_Score ~ Training_Hours_Per_Week + Training_Intensity, data = data_clean)
model_acl <- lm(ACL_Risk_Score ~ Training_Hours_Per_Week + Training_Intensity, data = data_clean)

data_clean$LB_adjusted  <- residuals(model_lb)
data_clean$ACL_adjusted <- residuals(model_acl)

# Plot hasil MANCOVA
ggplot(data_clean, aes(x = Position, y = LB_adjusted, fill = Position)) +
  geom_boxplot() +
  theme_minimal() +
  labs(title = "MANCOVA: Adjusted Load Balance Score")

ggplot(data_clean, aes(x = Position, y = ACL_adjusted, fill = Position)) +
  geom_boxplot() +
  theme_minimal() +
  labs(title = "MANCOVA: Adjusted ACL Risk Score")

9. Perbandingan Effect: MANOVA vs MANCOVA

9.1 Tabel Ringkasan Multivariate

manova_sum  <- summary(model_manova,  test = "Pillai")
mancova_sum <- summary(model_mancova, test = "Pillai")

# Ekstrak statistik Pillai untuk efek Position
pillai_manova  <- manova_sum$stats["Position", "Pillai"]
f_manova       <- manova_sum$stats["Position", "approx F"]
p_manova       <- manova_sum$stats["Position", "Pr(>F)"]

pillai_mancova <- mancova_sum$stats["Position", "Pillai"]
f_mancova      <- mancova_sum$stats["Position", "approx F"]
p_mancova      <- mancova_sum$stats["Position", "Pr(>F)"]

comparison_table <- data.frame(
  Model     = c("MANOVA", "MANCOVA"),
  Pillai    = round(c(pillai_manova, pillai_mancova), 4),
  F_approx  = round(c(f_manova, f_mancova), 4),
  p_value   = round(c(p_manova, p_mancova), 4),
  Signifikan = ifelse(c(p_manova, p_mancova) < 0.05, "Ya ✓", "Tidak ✗")
)

print(comparison_table)
##     Model Pillai F_approx p_value Signifikan
## 1  MANOVA 0.0255   1.2707  0.2809    Tidak ✗
## 2 MANCOVA 0.0314   1.5567  0.1852    Tidak ✗

9.2 Tabel Ringkasan Univariat per DV

# Ambil F dan p dari summary.aov
aov_manova  <- summary.aov(model_manova)
aov_mancova <- summary.aov(model_mancova)

get_fp <- function(aov_list, term, dv_name) {
  tbl <- aov_list[[dv_name]]
  row <- rownames(tbl)[trimws(rownames(tbl)) == term]
  if (length(row) == 0) return(c(NA, NA))
  c(tbl[row, "F value"], tbl[row, "Pr(>F)"])
}

dv_names <- trimws(names(aov_mancova))
rows <- list()

for (dv in dv_names) {
  fp_mancova <- get_fp(aov_mancova, "Position", dv)

  rows[[dv]] <- data.frame(
    DV          = dv,
    F_MANCOVA   = round(fp_mancova[1], 3),
    p_MANCOVA   = round(fp_mancova[2], 4)
  )
}

uni_table <- do.call(rbind, rows)
rownames(uni_table) <- NULL
print(uni_table)
##                            DV F_MANCOVA p_MANCOVA
## 1 Response Load_Balance_Score        NA        NA
## 2     Response ACL_Risk_Score        NA        NA

9.3 Effect Size Kovariat (η² Parsial)

# Hitung eta-squared parsial untuk kovariat di MANCOVA (per DV)
eta_sq_partial <- function(aov_list, dv_name) {
  dv_name <- trimws(dv_name)

  tbl <- aov_list[[dv_name]]
  if (is.null(tbl)) return(NULL)

  ss <- tbl[, "Sum Sq"]
  terms <- trimws(rownames(tbl))
  names(ss) <- terms

  if (!"Residuals" %in% names(ss)) return(NULL)

  ss_resid <- ss["Residuals"]

  kovariat_terms <- c("Training_Hours_Per_Week", "Training_Intensity")

  result <- data.frame()

  for (kt in kovariat_terms) {
    if (kt %in% names(ss)) {
      eta2p <- ss[kt] / (ss[kt] + ss_resid)

      result <- rbind(result, data.frame(
        DV     = dv_name,
        Term   = kt,
        eta2_p = round(eta2p, 4)
      ))
    }
  }

  result
}

eta_lb  <- eta_sq_partial(aov_mancova, "Load_Balance_Score")
eta_acl <- eta_sq_partial(aov_mancova, "ACL_Risk_Score")
eta_all <- rbind(eta_lb, eta_acl)
rownames(eta_all) <- NULL

cat("Effect Size (η² Parsial) Kovariat dalam MANCOVA\n")
## Effect Size (η² Parsial) Kovariat dalam MANCOVA
print(eta_all)
## NULL
cat("\nKriteria: kecil = 0.01, sedang = 0.06, besar = 0.14\n")
## 
## Kriteria: kecil = 0.01, sedang = 0.06, besar = 0.14