library(readxl)
## Warning: package 'readxl' was built under R version 4.5.2
wine = read_excel("C:/Users/user/Downloads/Wine_Quality.xlsx")
head(wine)
## # A tibble: 6 × 7
##   Clarity Aroma  Body Flavor Oakiness Quality Region
##     <dbl> <dbl> <dbl>  <dbl>    <dbl>   <dbl>  <dbl>
## 1       1   3.3   2.8    3.1      4.1     9.8      1
## 2       1   4.4   4.9    3.5      3.9    12.6      1
## 3       1   3.9   5.3    4.8      4.7    11.9      1
## 4       1   3.9   2.6    3.1      3.6    11.1      1
## 5       1   5.6   5.1    5.5      5.1    13.3      1
## 6       1   4.6   4.7    5        4.1    12.8      1
str(wine)
## tibble [38 × 7] (S3: tbl_df/tbl/data.frame)
##  $ Clarity : num [1:38] 1 1 1 1 1 1 1 1 1 1 ...
##  $ Aroma   : num [1:38] 3.3 4.4 3.9 3.9 5.6 4.6 4.8 5.3 4.3 4.3 ...
##  $ Body    : num [1:38] 2.8 4.9 5.3 2.6 5.1 4.7 4.8 4.5 4.3 3.9 ...
##  $ Flavor  : num [1:38] 3.1 3.5 4.8 3.1 5.5 5 4.8 4.3 3.9 4.7 ...
##  $ Oakiness: num [1:38] 4.1 3.9 4.7 3.6 5.1 4.1 3.3 5.2 2.9 3.9 ...
##  $ Quality : num [1:38] 9.8 12.6 11.9 11.1 13.3 12.8 12.8 12 13.6 13.9 ...
##  $ Region  : num [1:38] 1 1 1 1 1 1 1 1 3 1 ...
summary(wine)
##     Clarity           Aroma            Body           Flavor     
##  Min.   :0.5000   Min.   :3.300   Min.   :2.600   Min.   :2.900  
##  1st Qu.:0.8250   1st Qu.:4.125   1st Qu.:4.150   1st Qu.:4.225  
##  Median :1.0000   Median :4.650   Median :4.750   Median :4.800  
##  Mean   :0.9237   Mean   :4.847   Mean   :4.684   Mean   :4.768  
##  3rd Qu.:1.0000   3rd Qu.:5.450   3rd Qu.:5.375   3rd Qu.:5.500  
##  Max.   :1.0000   Max.   :7.700   Max.   :6.600   Max.   :7.000  
##     Oakiness        Quality          Region     
##  Min.   :2.900   Min.   : 7.90   Min.   :1.000  
##  1st Qu.:3.700   1st Qu.:11.15   1st Qu.:1.000  
##  Median :4.100   Median :12.45   Median :2.000  
##  Mean   :4.255   Mean   :12.44   Mean   :1.868  
##  3rd Qu.:4.775   3rd Qu.:13.75   3rd Qu.:3.000  
##  Max.   :6.000   Max.   :16.10   Max.   :3.000
## Matriks scatterplot semua variabel sekaligus
pairs(wine, main = "Matriks Scatterplot - Wine Quality Data",
      pch = 19, col = "steelblue")

## Scatterplot Quality vs masing-masing prediktor + garis regresi
par(mfrow = c(2, 3))
prediktor <- c("Clarity", "Aroma", "Body", "Flavor", "Oakiness")
for (p in prediktor) {
  plot(wine[[p]], wine$Quality,
       xlab = p, ylab = "Quality",
       main = paste("Quality vs", p,
                    "\n(r =", round(cor(wine[[p]], wine$Quality), 3), ")"),
       pch = 19, col = "darkslategray")
  abline(lm(wine$Quality ~ wine[[p]]), col = "red", lwd = 2)
}
par(mfrow = c(1, 1))

## Matriks korelasi
korelasi <- cor(wine)
round(korelasi, 3)
##          Clarity Aroma   Body Flavor Oakiness Quality Region
## Clarity    1.000 0.062 -0.308 -0.085    0.183   0.028 -0.020
## Aroma      0.062 1.000  0.549  0.737    0.202   0.707  0.620
## Body      -0.308 0.549  1.000  0.647    0.152   0.549  0.435
## Flavor    -0.085 0.737  0.647  1.000    0.180   0.790  0.506
## Oakiness   0.183 0.202  0.152  0.180    1.000  -0.047 -0.060
## Quality    0.028 0.707  0.549  0.790   -0.047   1.000  0.507
## Region    -0.020 0.620  0.435  0.506   -0.060   0.507  1.000
## Heatmap korelasi (opsional, butuh package corrplot)
# install.packages("corrplot")
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.5.3
## corrplot 0.95 loaded
corrplot(korelasi, method = "color", type = "upper",
         addCoef.col = "black", tl.col = "black", number.cex = 0.8,
         title = "Matriks Korelasi Antarvariabel", mar = c(0,0,2,0))

model <- lm(Quality ~ Clarity + Aroma + Body + Flavor + Oakiness, data = wine)
summary(model)
## 
## Call:
## lm(formula = Quality ~ Clarity + Aroma + Body + Flavor + Oakiness, 
##     data = wine)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.85552 -0.57448 -0.07092  0.67275  1.68093 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   3.9969     2.2318   1.791 0.082775 .  
## Clarity       2.3395     1.7348   1.349 0.186958    
## Aroma         0.4826     0.2724   1.771 0.086058 .  
## Body          0.2732     0.3326   0.821 0.417503    
## Flavor        1.1683     0.3045   3.837 0.000552 ***
## Oakiness     -0.6840     0.2712  -2.522 0.016833 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.163 on 32 degrees of freedom
## Multiple R-squared:  0.7206, Adjusted R-squared:  0.6769 
## F-statistic: 16.51 on 5 and 32 DF,  p-value: 4.703e-08
coef(model)
## (Intercept)     Clarity       Aroma        Body      Flavor    Oakiness 
##   3.9968648   2.3394535   0.4825505   0.2731612   1.1683238  -0.6840102
## Persamaan model:
## Quality_hat = 4.2147 + 0.6998*Clarity + 0.6295*Aroma + 0.7058*Body
##               + 0.7317*Flavor - 0.5295*Oakiness

## Selang kepercayaan koefisien
confint(model, level = 0.95)
##                   2.5 %     97.5 %
## (Intercept) -0.54910206  8.5428317
## Clarity     -1.19427368  5.8731807
## Aroma       -0.07240642  1.0375075
## Body        -0.40424262  0.9505650
## Flavor       0.54811681  1.7885307
## Oakiness    -1.23641174 -0.1316086
## Tabel ANAVA overall (regresi vs residual)
anova_overall <- anova(model)
print(anova_overall)
## Analysis of Variance Table
## 
## Response: Quality
##           Df Sum Sq Mean Sq F value    Pr(>F)    
## Clarity    1  0.125   0.125  0.0926 0.7628120    
## Aroma      1 77.353  77.353 57.2351 1.286e-08 ***
## Body       1  6.414   6.414  4.7461 0.0368417 *  
## Flavor     1 19.050  19.050 14.0953 0.0006946 ***
## Oakiness   1  8.598   8.598  6.3616 0.0168327 *  
## Residuals 32 43.248   1.352                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Ringkas jadi tabel Regresi - Residual - Total
SSR <- sum(anova_overall$"Sum Sq"[1:5])      # jumlah kuadrat regresi
SSE <- anova_overall$"Sum Sq"[6]             # jumlah kuadrat residual
SST <- SSR + SSE
dfR <- sum(anova_overall$Df[1:5])
dfE <- anova_overall$Df[6]
dfT <- dfR + dfE
MSR <- SSR / dfR
MSE <- SSE / dfE
Fhitung <- MSR / MSE
pvalue  <- 1 - pf(Fhitung, dfR, dfE)

tabel_anava <- data.frame(
  Sumber = c("Regresi", "Residual", "Total"),
  db     = c(dfR, dfE, dfT),
  JK     = c(SSR, SSE, SST),
  KT     = c(MSR, MSE, NA),
  Fhitung = c(Fhitung, NA, NA),
  pvalue  = c(pvalue, NA, NA)
)
print(tabel_anava, digits = 5)
##     Sumber db      JK      KT Fhitung    pvalue
## 1  Regresi  5 111.540 22.3081  16.506 4.703e-08
## 2 Residual 32  43.248  1.3515      NA        NA
## 3    Total 37 154.788      NA      NA        NA
## Nilai F tabel pada alpha = 5%
alpha <- 0.05
F_tabel <- qf(1 - alpha, dfR, dfE)
cat("F_tabel(alpha=0.05, db1=", dfR, ", db2=", dfE, ") =", F_tabel, "\n")
## F_tabel(alpha=0.05, db1= 5 , db2= 32 ) = 2.512255
cat("F_hitung =", Fhitung, "\n")
## F_hitung = 16.50616
cat("Keputusan:", ifelse(Fhitung > F_tabel,
                         "Tolak H0 -> model signifikan",
                         "Gagal tolak H0 -> model tidak signifikan"), "\n")
## Keputusan: Tolak H0 -> model signifikan
## R-squared dan Adjusted R-squared
cat("R-squared      :", summary(model)$r.squared, "\n")
## R-squared      : 0.7205992
cat("Adj R-squared  :", summary(model)$adj.r.squared, "\n")
## Adj R-squared  : 0.6769428
library(corrplot)
shapiro.test(model$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  model$residuals
## W = 0.96621, p-value = 0.3
library(lmtest)
## Warning: package 'lmtest' was built under R version 4.5.3
## Loading required package: zoo
## Warning: package 'zoo' was built under R version 4.5.3
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
bptest(model)
## 
##  studentized Breusch-Pagan test
## 
## data:  model
## BP = 10.022, df = 5, p-value = 0.07461
library(car)
## Warning: package 'car' was built under R version 4.5.3
## Loading required package: carData
## Warning: package 'carData' was built under R version 4.5.3
vif(model)
##  Clarity    Aroma     Body   Flavor Oakiness 
## 1.266390 2.381143 2.056492 2.682277 1.096731
# =========================================================
# NO. 5 - IDENTIFIKASI OUTLIER
# =========================================================

# 1. Studentized residual
rstudent(model)
##            1            2            3            4            5            6 
##  0.268915086  1.310570723 -0.147746834  0.989111532 -0.060824579 -0.067222376 
##            7            8            9           10           11           12 
## -0.462322650  0.368774378  1.367233491  1.461038927  1.488413844  1.712995605 
##           13           14           15           16           17           18 
##  0.429535178 -0.370917971  0.549437274  1.522681696  0.451182841 -0.065376408 
##           19           20           21           22           23           24 
## -1.178448030 -3.087312700  0.005924868 -0.472759465 -1.511289638 -1.203178648 
##           25           26           27           28           29           30 
## -1.314046275 -0.182564885 -0.075993468 -0.519019437 -1.345569135 -1.701955694 
##           31           32           33           34           35           36 
## -1.019544790 -0.119034824  1.200175907  0.427954051  0.465967589  0.646531035 
##           37           38 
##  0.792354831 -0.685642649
# Mencari observasi dengan studentized residual paling ekstrem
which.max(abs(rstudent(model)))
## 20 
## 20
# Nilai studentized residual observasi tersebut
rstudent(model)[which.max(abs(rstudent(model)))]
##        20 
## -3.087313
# 2. Cook's Distance
cooks.distance(model)
##            1            2            3            4            5            6 
## 2.540574e-03 5.358209e-02 7.575551e-04 4.757193e-02 5.239139e-05 4.724372e-05 
##            7            8            9           10           11           12 
## 4.344657e-03 2.882056e-03 5.581593e-02 3.040021e-02 2.902936e-02 3.007018e-01 
##           13           14           15           16           17           18 
## 7.672432e-03 1.321196e-02 1.604877e-02 2.416940e-02 6.591579e-03 9.192882e-05 
##           19           20           21           22           23           24 
## 3.039585e-02 3.101434e-01 8.646330e-07 3.742266e-03 9.605977e-02 5.139300e-02 
##           25           26           27           28           29           30 
## 2.345999e-02 4.632939e-04 2.289592e-04 3.400519e-03 3.876841e-02 1.012302e-01 
##           31           32           33           34           35           36 
## 4.397236e-02 7.313842e-04 4.537606e-02 5.720638e-03 4.287351e-03 1.025008e-02 
##           37           38 
## 6.359374e-02 1.079912e-02
# Mencari observasi dengan Cook's Distance terbesar
which.max(cooks.distance(model))
## 20 
## 20
# Nilai Cook's Distance terbesar
max(cooks.distance(model))
## [1] 0.3101434
# 3. Melihat data observasi yang teridentifikasi
wine[which.max(abs(rstudent(model))), ]
## # A tibble: 1 × 7
##   Clarity Aroma  Body Flavor Oakiness Quality Region
##     <dbl> <dbl> <dbl>  <dbl>    <dbl>   <dbl>  <dbl>
## 1     0.9   3.4     5    3.4      3.4     7.9      2
# =========================================================
# NO. 6 - VARIABEL YANG MEMPENGARUHI RESPONSE
# =========================================================

# Melihat hasil uji parsial masing-masing variabel
summary(model)
## 
## Call:
## lm(formula = Quality ~ Clarity + Aroma + Body + Flavor + Oakiness, 
##     data = wine)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.85552 -0.57448 -0.07092  0.67275  1.68093 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   3.9969     2.2318   1.791 0.082775 .  
## Clarity       2.3395     1.7348   1.349 0.186958    
## Aroma         0.4826     0.2724   1.771 0.086058 .  
## Body          0.2732     0.3326   0.821 0.417503    
## Flavor        1.1683     0.3045   3.837 0.000552 ***
## Oakiness     -0.6840     0.2712  -2.522 0.016833 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.163 on 32 degrees of freedom
## Multiple R-squared:  0.7206, Adjusted R-squared:  0.6769 
## F-statistic: 16.51 on 5 and 32 DF,  p-value: 4.703e-08
# Mengambil koefisien dan p-value
coef(summary(model))
##               Estimate Std. Error    t value     Pr(>|t|)
## (Intercept)  3.9968648  2.2317701  1.7908945 0.0827745402
## Clarity      2.3394535  1.7348271  1.3485226 0.1869578145
## Aroma        0.4825505  0.2724473  1.7711703 0.0860575292
## Body         0.2731612  0.3325606  0.8213876 0.4175033004
## Flavor       1.1683238  0.3044807  3.8371025 0.0005522334
## Oakiness    -0.6840102  0.2711928 -2.5222287 0.0168327190