Περιγραφή του Dataset και της πηγής του

Το παρόν Case Study εξετάζει την κερδοφορία αεροπορικών δρομολογίων. Το Dataset περιλαμβάνει πάνω από 7.500 πτήσεις σε 30 δρομολόγια από το Ντουμπάι (DXB). Κάθε εγγραφή περιέχει στοιχεία λειτουργίας της πτήσης (τύπος αεροσκάφους, επιβάτες, πληρότητα, ώρες πτήσης), οικονομικά δεδομένα εσόδων και αναλυτικές κατηγορίες κόστους (π.χ. καύσιμα, πλήρωμα, συντήρηση). Επιπλέον, παρέχει δείκτες κερδοφορίας και πληροφορίες για τις εποχιακές διακυμάνσεις της ζήτησης. Στόχος είναι η δημιουργία ενός μοντέλου που προβλέπει τα Συνολικά Έσοδα (Total_Revenue).

Χρησιμοποιούμε δύο ξεχωριστά σύνολα δεδομένων:

airline_route_train.csv: Για την εκπαίδευση και διερεύνηση του μοντέλου.

airline_route_test.csv: Για την αξιολόγηση της ικανότητας πρόβλεψης σε νέα δεδομένα.


Περιγραφή των μεταβλητών

Ενδεικτικά, μερικές από τις σημαντικότερες μεταβλητές του Dataset είναι:


Βήμα 1:

Στο πρώτο βήμα, αναλύουμε τις συσχετίσεις και την κατανομή των δεδομένων για να επιλέξουμε τις κατάλληλες ανεξάρτητες μεταβλητές.

Εισαγωγή του Dataset

train <- read.csv("airline_route_train.csv")
test <- read.csv("airline_route_test.csv")

colnames(train) <- make.names(colnames(train))
colnames(test) <- make.names(colnames(test))

Επισκόπηση δομής

str(train)
## 'data.frame':    6379 obs. of  33 variables:
##  $ Flight_Number          : chr  "EK8960" "EK3960" "EK7529" "EK4543" ...
##  $ Flight_Date            : chr  "20-12-24" "13-05-24" "12-10-24" "25-06-24" ...
##  $ Origin                 : chr  "DXB" "DXB" "DXB" "DXB" ...
##  $ Destination            : chr  "ORD" "HYD" "CDG" "DEL" ...
##  $ Route                  : chr  "DXB-ORD" "DXB-HYD" "DXB-CDG" "DXB-DEL" ...
##  $ Aircraft_Type          : chr  "Boeing 777-300ER" "Boeing 787-9" "Boeing 787-9" "Boeing 787-9" ...
##  $ Aircraft_Capacity      : int  396 296 296 296 180 180 296 189 180 296 ...
##  $ Passengers             : int  308 234 251 229 142 171 281 148 171 281 ...
##  $ Load_Factor            : num  0.779 0.791 0.85 0.775 0.79 ...
##  $ Flight_Hours           : num  14.5 4.2 7.5 3.5 2.2 2 5 1.5 2 5 ...
##  $ Season                 : chr  "Peak" "Normal" "Shoulder" "Low" ...
##  $ Route_Category         : chr  "Long Haul" "Medium Haul" "Long Haul" "Medium Haul" ...
##  $ Demand_Level           : chr  "Medium" "Medium" "High" "High" ...
##  $ Ticket_Revenue         : num  410785 145890 602841 126485 32651 ...
##  $ Ancillary_Revenue      : num  53432 17695 78724 17543 3872 ...
##  $ Total_Revenue          : num  464217 163585 681565 144028 36523 ...
##  $ Fuel_Cost              : num  131034 21339 41012 17334 5577 ...
##  $ Maintenance_Cost       : int  50750 9240 16500 7700 2530 2300 11000 1800 2300 11000 ...
##  $ Crew_Cost              : int  21750 5040 9000 4200 1716 1560 6000 1200 1560 6000 ...
##  $ Depreciation_Cost      : int  65250 13440 24000 11200 3740 3400 16000 2700 3400 16000 ...
##  $ Insurance_Cost         : int  11600 2520 4500 2100 616 560 3000 450 560 3000 ...
##  $ Airport_Fees           : num  4262 2017 10765 6508 4719 ...
##  $ Catering_Cost          : num  5186 5851 4134 6509 3361 ...
##  $ Handling_Cost          : num  4460 5426 3762 4441 3414 ...
##  $ Navigation_Fees        : num  10637 3027 3432 2080 1662 ...
##  $ Sales_Distribution_Cost: num  78194 21586 100189 22687 5134 ...
##  $ Passenger_Service_Cost : num  5100 6022 6514 4791 3095 ...
##  $ Overhead_Cost          : num  88546 17058 31347 15329 8252 ...
##  $ Marketing_Cost         : num  25884 8821 23695 6795 1493 ...
##  $ IT_Systems_Cost        : num  3769 1938 3416 2246 1273 ...
##  $ Total_Cost             : num  506422 123324 282266 113919 46581 ...
##  $ Profit                 : num  -42204 40262 399299 30109 -10058 ...
##  $ Profit_Margin          : num  -9.09 24.61 58.59 20.91 -27.54 ...
summary(train$Total_Revenue)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   17311   63123  201647  296499  462645 1496567

Οπτικοποίηση Συσχετίσεων

# Έλεγχος συσχετίσεων για τις βασικές παραμέτρους
numeric_vars <- train %>% select(Total_Revenue, Passengers, Flight_Hours, Load_Factor, Fuel_Cost, Total_Cost, Profit_Margin)
cor_matrix <- cor(numeric_vars)
corrplot(cor_matrix, method = "number", type = "upper")

Ερμηνεία Συσχετίσεων

Μετά την οπτικοποίηση του πίνακα συσχετίσεων (corrplot), προκύπτουν κρίσιμα συμπεράσματα που καθοδηγούν την επιλογή των μεταβλητών για το μοντέλο παλινδρόμησης:

  • Έσοδα και Επιβάτες (\(r = 0.80\)): Η ισχυρή θετική συσχέτιση επιβεβαιώνει ότι ο αριθμός των επιβατών αποτελεί τον κύριο προσδιοριστικό παράγοντα (driver) των συνολικών εσόδων. Η τιμή \(0.80\) υποδηλώνει μια πολύ ισχυρή γραμμική σχέση, καθιστώντας τη μεταβλητή Passengers την καταλληλότερη για το αρχικό μοντέλο απλής παλινδρόμησης.

  • Καύσιμα και Διάρκεια Πτήσης (\(r = 0.89\)): Παρατηρείται εξαιρετικά ισχυρή συσχέτιση μεταξύ των ωρών πτήσης (Flight_Hours) και του συνολικού κόστους (Total_Cost). Αυτό ερμηνεύεται από το γεγονός ότι οι πτήσεις μεγαλύτερης διάρκειας επιβαρύνονται αναλογικά περισσότερο από μεταβλητά έξοδα, με κυριότερο το κόστος καυσίμων (Fuel_Cost), το οποίο επίσης παρουσιάζει υψηλή συνάφεια με τα έσοδα (\(r = 0.98\)).

  • Σχέση Εσόδων - Κόστους (\(r = 0.88\)): Η πολύ υψηλή συσχέτιση υποδηλώνει ότι η αύξηση της επιχειρησιακής κλίμακας (π.χ. μεγαλύτερα αεροσκάφη ή μακρινότερα δρομολόγια) αυξάνει τα έσοδα, αλλά συνοδεύεται από σχεδόν παράλληλη αύξηση των εξόδων. Αυτό εξηγεί γιατί η πρόβλεψη των εσόδων είναι συχνά πιο “σταθερή” στατιστικά από την πρόβλεψη του καθαρού κέρδους.

  • Αποδοτικότητα και Load Factor (\(r = 0.42\)): Η μέτρια θετική συσχέτιση μεταξύ του περιθωρίου κέρδους (Profit_Margin) και της πληρότητας (Load_Factor) υποδεικνύει ότι, αν και η γεμάτη καμπίνα συμβάλλει στην κερδοφορία, δεν την εξασφαλίζει από μόνη της. Παράγοντες όπως η τιμολογιακή πολιτική (yield management) και η αποτελεσματική διαχείριση των λειτουργικών εξόδων παίζουν εξίσου σημαντικό ρόλο.Συμπέρασμα για το επόμενο στάδιο:Λαμβάνοντας υπόψη τα παραπάνω, στο Βήμα 2 θα προχωρήσουμε στη δημιουργία ενός μοντέλου που θα περιλαμβάνει τις μεταβλητές με τη μεγαλύτερη ερμηνευτική ισχύ (Passengers, Fuel_Cost και Flight_Hours), ενώ θα εξετάσουμε τη “στιβαρότητα” (robustness) του μοντέλου αφαιρώντας μεταβλητές με χαμηλότερη συσχέτιση όπως ο Load_Factor.


Βήμα 2:

Δημιουργία και Αξιολόγηση ΜοντέλουΘα ακολουθήσουμε τη διαδικασία προσθήκης και αφαίρεσης μεταβλητών για να καταλήξουμε στο βέλτιστο μοντέλο.

2α. Σύγκριση Μοντέλων (Simple vs Multiple)

Ξεκινάμε με ένα απλό μοντέλο και προσθέτουμε μεταβλητές για να αυξήσουμε το \(R^2\).

# Μοντέλο 1: Απλή Παλινδρόμηση
model1 <- lm(Total_Revenue ~ Passengers, data = train)
summary(model1)
## 
## Call:
## lm(formula = Total_Revenue ~ Passengers, data = train)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -646333 -100011  -12036   89015  625574 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -320799.6     6163.0  -52.05   <2e-16 ***
## Passengers     2427.3       22.9  106.01   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 161200 on 6377 degrees of freedom
## Multiple R-squared:  0.638,  Adjusted R-squared:  0.6379 
## F-statistic: 1.124e+04 on 1 and 6377 DF,  p-value: < 2.2e-16
# Υπολογισμός SSE1
SSE1 <- sum(model1$residuals^2)
cat("Sum of Squared Errors (SSE1):", SSE1)
## Sum of Squared Errors (SSE1): 1.656448e+14
# Μοντέλο 2: Πολλαπλή Παλινδρόμηση (Προσθήκη Flight_Hours & Fuel_Cost & Load_Factor)
model2 <- lm(Total_Revenue ~ Passengers + Flight_Hours + Fuel_Cost + Load_Factor, data = train)
summary(model2)
## 
## Call:
## lm(formula = Total_Revenue ~ Passengers + Flight_Hours + Fuel_Cost + 
##     Load_Factor, data = train)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -535486  -82362   -9670   57900  753709 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -4.270e+05  1.678e+04 -25.437  < 2e-16 ***
## Passengers    1.591e+03  3.830e+01  41.529  < 2e-16 ***
## Flight_Hours  1.528e+04  1.111e+03  13.751  < 2e-16 ***
## Fuel_Cost     9.733e-01  1.486e-01   6.550 6.21e-11 ***
## Load_Factor   2.215e+05  2.317e+04   9.559  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 138500 on 6374 degrees of freedom
## Multiple R-squared:  0.7329, Adjusted R-squared:  0.7327 
## F-statistic:  4372 on 4 and 6374 DF,  p-value: < 2.2e-16
# Υπολογισμός SSE2
SSE2 <- sum(model2$residuals^2)
cat("Sum of Squared Errors (SSE2):", SSE2)
## Sum of Squared Errors (SSE2): 1.222066e+14
ggplot(train, aes(x = Passengers, y = Total_Revenue)) + 
  geom_point(alpha = 0.3) + 
  geom_smooth(method = "lm", col = "red") + 
  labs(title = "Μοντέλο Απλής Γραμμικής Παλινδρόμησης",
       x = "Passengers",
       y = "Total Revenue")

Σχολιασμός: Το R-squared δείχνει πόσο ποσοστό της διακύμανσης εξηγείται από το μοντέλο. Με \(r=0.80\), αναμένουμε ένα \(R^2 \approx 0.64\).


2β.Διαδικασία Αφαίρεσης (Backward Method) για Στιβαρότητα

Εξετάζουμε τα p-values του Μοντέλου 2. Αν κάποια μεταβλητή (π.χ. Load_Factor) δεν είναι σημαντική, την αφαιρούμε για να γίνει το μοντέλο στιβαρό (robust).

# Αφαίρεση του Load_Factor (Backward Elimination)
RobustModel <- lm(Total_Revenue ~ Passengers + Flight_Hours + Fuel_Cost, data = train)

# Υπολογισμός SSE και RMSE για το Robust Model στο Training Set
SSE_train <- sum(RobustModel$residuals^2)
RMSE_train <- sqrt(SSE_train/nrow(train))

cat("SSE (Training):", SSE_train, "\n")
## SSE (Training): 1.239586e+14
cat("RMSE (Training):", RMSE_train, "\n")
## RMSE (Training): 139399.8
cat("Adjusted R-squared (Robust):", summary(RobustModel)$adj.r.squared)
## Adjusted R-squared (Robust): 0.7289456

Σύγκριση: * Αν το SSE2 < SSE1, το μοντέλο με τις δύο μεταβλητές είναι ακριβέστερο.

Το Adjusted R-squared μας επιτρέπει να δούμε αν η προσθήκη της Flight_Hours προσφέρει ουσιαστική πληροφορία.


Βήμα 3: Εφαρμογή σε νέα δεδομένα - Πρόβλεψη

Χρησιμοποιούμε τη συνάρτηση predict() για να εκτιμήσουμε τα έσοδα μιας μελλοντικής πτήσης.

# Πρόβλεψη
Predictions <- predict(RobustModel, newdata = test)

plot_data <- data.frame(Actual = test$Total_Revenue, Predicted = Predictions)
ggplot(plot_data, aes(x = Actual, y = Predicted)) +
  geom_point(color = "darkgreen", alpha = 0.5) +
  geom_abline(slope = 1, intercept = 0, linetype = "dashed") +
  labs(title = "Πραγματικά vs Προβλεπόμενα Έσοδα (Test Set)")


### Βήμα 4: Διερεύνηση SSE και Out-of-Sample R-squared
#Σύμφωνα με τη θεωρία του μαθήματος, υπολογίζουμε τους δείκτες αξιολόγησης για το Test Set χειροκίνητα.

# 1. Υπολογισμός SSE (Sum of Squared Errors)
SSE_test <- sum((Predictions - test$Total_Revenue)^2)

# 2. Υπολογισμός SST (Total Sum of Squares) 
# Χρησιμοποιούμε τη μέση τιμή των εσόδων από το TRAINING SET
SST_test <- sum((mean(train$Total_Revenue) - test$Total_Revenue)^2)

# 3. Υπολογισμός Out-of-Sample R-squared
R2_test <- 1 - (SSE_test / SST_test)

# 4. Υπολογισμός RMSE (Root Mean Square Error)
RMSE_test <- sqrt(SSE_test / nrow(test))

cat("Out-of-Sample R-squared:", R2_test, "\n")
## Out-of-Sample R-squared: 0.7217349
cat("Out-of-Sample RMSE:", RMSE_test)
## Out-of-Sample RMSE: 138196

Συμπεράσματα & Τεκμηρίωση

Απόδοση Μοντέλου: Το μοντέλο πέτυχε ένα Out-of-Sample \(R^2\) ύψους r round(R2_test, 4), το οποίο είναι πολύ κοντά στο \(R^2\) του training set.

  • Αυτό υποδηλώνει ότι το μοντέλο έχει υψηλή γενικευτική ισχύ και δεν παρουσιάζει φαινόμενα overfitting.

  • Στιβαρότητα: Η διαδικασία αφαίρεσης μεταβλητών (Backward) έδειξε ότι οι Passengers, Flight_Hours και Fuel_Cost είναι οι βασικοί οδηγοί των εσόδων.

  • Ο Load_Factor κρίθηκε πλεονασματικός.

  • Σφάλμα: Το RMSE στο test set (r round(RMSE_test, 2)) είναι ελαφρώς μεγαλύτερο από του training set, γεγονός που αναμενόταν και επιβεβαιώνει την ορθότητα της διαδικασίας.

  • Το μοντέλο κρίνεται έγκυρο και στιβαρό για τη λήψη επιχειρηματικών αποφάσεων.