## ── 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.2 ✔ 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
## Type 'citation("pROC")' for a citation.
##
## Attaching package: 'pROC'
##
## The following objects are masked from 'package:stats':
##
## cov, smooth, var
Το παρόν dataset περιλαμβάνει στατιστικά απόδοσης ομάδων του NBA, με στόχο την πρόβλεψη της συμμετοχής τους στα Playoffs μιας σεζόν. Κάθε γραμμή του dataset αντιπροσωπεύει μία ομάδα για μία συγκεκριμένη αγωνιστική περίοδο και περιέχει πληθώρα αγωνιστικών χαρακτηριστικών, όπως πόντους υπέρ και κατά, ποσοστά ευστοχίας, ριμπάουντ, ασίστ, κλεψίματα, λάθη και φάουλ.
Ο στόχος της ανάλυσης είναι η κατασκευή ενός μοντέλου Δέντρου Απόφασης (CART), το οποίο θα προβλέπει αν μια ομάδα θα προκριθεί στα Playoffs (Playoffs = 1) ή όχι (Playoffs = 0), βασιζόμενο στα παραπάνω αγωνιστικά χαρακτηριστικά. Περιγραφή μεταβλητών
Team: Όνομα ομάδας (δεν χρησιμοποιείται ως προβλεπτική μεταβλητή)
W / L: Νίκες και ήττες
PW / PL: Προβλεπόμενες νίκες/ήττες βάσει στατιστικής
MOV: Μέση διαφορά πόντων ανά παιχνίδι (Margin of Victory)
SOS: Δείκτης δυσκολίας προγράμματος (Strength of Schedule)
SRS: Ενιαίος δείκτης απόδοσης (MOV + SOS)
ORTG / DRTG / NRtg: Επιθετική, αμυντική και καθαρή αποτελεσματικότητα
PACE: Ρυθμός παιχνιδιού (κατοχές ανά 48')
FTr / X3PAr / TS.: Δείκτες σκοραρίσματος (βολές, τρίποντα, συνολική αποδοτικότητα)
TRB, AST, STL, BLK, TOV, PF: Ριμπάουντ, ασίστ, κλεψίματα, τάπες, λάθη, φάουλ
Playoffs: Εξαρτημένη μεταβλητή (1 = πρόκριση, 0 = αποκλεισμός)
# Ανάγνωση του αρχείου
nba_train <- read.csv("NBA_train.csv")
# Δημιουργία train/test set (70/30 split)
set.seed(123) # για επαναληψιμότητα
split <- sample.split(nba_train$Playoffs, SplitRatio = 0.7)
train_set <- subset(nba_train, split == TRUE)
test_set <- subset(nba_train, split == FALSE)
# Αφαίρεση μη προβλεπτικής μεταβλητής (Team)
train_set <- train_set %>% select(-Team)
test_set <- test_set %>% select(-Team)
# Μετατροπή της εξαρτημένης μεταβλητής σε factor
train_set$Playoffs <- as.factor(train_set$Playoffs)
test_set$Playoffs <- as.factor(test_set$Playoffs)
# Εξερεύνηση βασικών χαρακτηριστικών
str(train_set)## 'data.frame': 584 obs. of 19 variables:
## $ SeasonEnd: int 1980 1980 1980 1980 1980 1980 1980 1980 1980 1980 ...
## $ Playoffs : Factor w/ 2 levels "0","1": 2 1 1 1 2 1 2 1 1 2 ...
## $ W : int 50 30 30 16 41 37 49 34 39 59 ...
## $ PTS : int 8573 8813 8878 8933 9084 9119 9025 8879 9344 8949 ...
## $ oppPTS : int 8334 9035 9240 9609 9070 9176 8702 8975 9438 8603 ...
## $ FG : int 3261 3362 3462 3643 3599 3639 3685 3456 3802 3523 ...
## $ FGA : int 7027 6943 7470 7596 7496 7689 7553 7504 7672 7156 ...
## $ X2P : int 3248 3292 3379 3586 3495 3551 3635 3371 3760 3496 ...
## $ X2PA : int 6952 6668 7215 7377 7117 7375 7398 7206 7481 7031 ...
## $ X3P : int 13 70 83 57 104 88 50 85 42 27 ...
## $ X3PA : int 75 275 255 219 379 314 155 298 191 125 ...
## $ FT : int 2038 2019 1871 1590 1782 1753 1605 1882 1698 1876 ...
## $ FTA : int 2645 2592 2539 2149 2326 2333 2102 2406 2274 2431 ...
## $ ORB : int 1369 1115 1311 1226 1394 1398 1245 1229 1236 1187 ...
## $ DRB : int 2406 2465 2524 2415 2217 2326 2396 2535 2303 2635 ...
## $ AST : int 1913 2152 2079 1950 2149 2148 2277 2094 2265 2226 ...
## $ STL : int 782 704 746 783 782 900 778 869 881 792 ...
## $ BLK : int 539 392 404 562 373 530 510 581 457 652 ...
## $ TOV : int 1495 1684 1533 1742 1565 1517 1496 1702 1613 1708 ...
## [1] 584 19
## SeasonEnd Playoffs W PTS oppPTS FG FGA X2P X2PA X3P X3PA FT FTA ORB
## 1 1980 1 50 8573 8334 3261 7027 3248 6952 13 75 2038 2645 1369
## 3 1980 0 30 8813 9035 3362 6943 3292 6668 70 275 2019 2592 1115
## 5 1980 0 30 8878 9240 3462 7470 3379 7215 83 255 1871 2539 1311
## 6 1980 0 16 8933 9609 3643 7596 3586 7377 57 219 1590 2149 1226
## 8 1980 1 41 9084 9070 3599 7496 3495 7117 104 379 1782 2326 1394
## 9 1980 0 37 9119 9176 3639 7689 3551 7375 88 314 1753 2333 1398
## DRB AST STL BLK TOV
## 1 2406 1913 782 539 1495
## 3 2465 2152 704 392 1684
## 5 2524 2079 746 404 1533
## 6 2415 1950 783 562 1742
## 8 2217 2149 782 373 1565
## 9 2326 2148 900 530 1517
## SeasonEnd Playoffs W PTS oppPTS FG FGA X2P
## 0 0 0 0 0 0 0 0
## X2PA X3P X3PA FT FTA ORB DRB AST
## 0 0 0 0 0 0 0 0
## STL BLK TOV
## 0 0 0
Για την κατασκευή των μοντέλων λογιστικής παλινδρόμησης και CART,
επιλέχθηκε ένα σύνολο μεταβλητών που θεωρούνται σχετικές με την πρόβλεψη
της πρόκρισης στα Playoffs. Η μεταβλητή W (Νίκες),
παρότι παρουσιάζει ισχυρή συσχέτιση με την εξαρτημένη μεταβλητή, δεν
περιλήφθηκε στη μοντελοποίηση. Ο λόγος είναι ότι η W
ουσιαστικά αντανακλά άμεσα την τελική έκβαση της πρόκρισης και η χρήση
της θα περιόριζε τη δυνατότητα ανάδειξης των υποκείμενων παραγόντων
απόδοσης που συμβάλλουν στην επιτυχία.
Το τελικό σύνολο μεταβλητών περιλαμβάνει: - PTS (πόντοι υπέρ), - AST (ασίστ), - TOV (λάθη), - FG (εύστοχα σουτ), - oppPTS (πόντοι κατά).
Η επιλογή βασίστηκε στη στατιστική συσχέτιση των μεταβλητών με την πρόκριση και στη σημασία τους σε προηγούμενες αναλύσεις. Με βάση τις μεταβλητές αυτές κατασκευάστηκαν δύο μοντέλα: ένα μοντέλο λογιστικής παλινδρόμησης και ένα δέντρο απόφασης (CART).
# Προαιρετικό: αρχική λίστα για άλλες δοκιμές (δεν χρησιμοποιείται στο τελικό μοντέλο)
vars <- c("W", "PTS", "oppPTS", "FG", "FGA", "X3P", "X3PA", "FT", "FTA",
"ORB", "DRB", "AST", "STL", "BLK", "TOV")
# Μετονομασία των 3P / 3PA ώστε να είναι συμβατές με R
colnames(nba_train)[which(names(nba_train) == "3P")] <- "X3P"
colnames(nba_train)[which(names(nba_train) == "3PA")] <- "X3PA"
colnames(test_set)[which(names(test_set) == "3P")] <- "X3P"
colnames(test_set)[which(names(test_set) == "3PA")] <- "X3PA"log_model <- glm(Playoffs ~ PTS + AST + TOV + FG + oppPTS,
data = nba_train, family = "binomial")
summary(log_model)##
## Call:
## glm(formula = Playoffs ~ PTS + AST + TOV + FG + oppPTS, family = "binomial",
## data = nba_train)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -3.6093296 2.3410071 -1.542 0.123126
## PTS 0.0130927 0.0012244 10.693 < 2e-16 ***
## AST 0.0041483 0.0012379 3.351 0.000805 ***
## TOV -0.0004847 0.0011697 -0.414 0.678597
## FG -0.0028836 0.0017426 -1.655 0.097964 .
## oppPTS -0.0123285 0.0010028 -12.295 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 1138.77 on 834 degrees of freedom
## Residual deviance: 365.89 on 829 degrees of freedom
## AIC: 377.89
##
## Number of Fisher Scoring iterations: 7
Η αξιολόγηση των δύο μοντέλων πραγματοποιείται στο σύνολο ελέγχου
(test_set) που δημιουργήθηκε με τυχαίο διαχωρισμό των
αρχικών δεδομένων. Για κάθε μοντέλο υπολογίζονται:
# Προβλέψεις πιθανοτήτων
log_pred_probs <- predict(log_model, newdata = test_set[, vars], type = "response")## Προβλεπόμενο
## Πραγματικό 0 1
## 0 96 11
## 1 8 136
# Confusion Matrix
conf_log <- table(Πραγματικό = test_set$Playoffs, Προβλεπόμενο = log_pred_class)
# Εξαγωγή τιμών
TP <- conf_log["1", "1"]
FP <- conf_log["0", "1"]
FN <- conf_log["1", "0"]
TN <- conf_log["0", "0"]
# Precision, Recall, F1, Specificity
precision_log <- TP / (TP + FP)
recall_log <- TP / (TP + FN)
# Εμφάνιση
precision_log; recall_log; ## [1] 0.9251701
## [1] 0.9444444
## Προβλεπόμενο
## Πραγματικό 0 1
## 0 94 13
## 1 9 135
conf_cart <- table(Πραγματικό = test_set$Playoffs, Προβλεπόμενο = cart_pred)
TP <- conf_cart["1", "1"]
FP <- conf_cart["0", "1"]
FN <- conf_cart["1", "0"]
TN <- conf_cart["0", "0"]
precision_cart <- TP / (TP + FP)
recall_cart <- TP / (TP + FN)
precision_cart; recall_cart; ## [1] 0.9121622
## [1] 0.9375
Η σύγκριση των μοντέλων πραγματοποιήθηκε στο σύνολο ελέγχου που προέκυψε από τυχαίο διαχωρισμό του αρχικού dataset. Χρησιμοποιήθηκαν τα ίδια σύνολα μεταβλητών για τη λογιστική παλινδρόμηση και το CART, προκειμένου να διασφαλιστεί η συγκρισιμότητα.