Σε αυτή την εργασία θα αναλύσουμε ένα σύνολο δεδομένων που αφορά πελάτες ενός εμπορικού κέντρου (Mall). Ο σκοπός μας είναι να εντοπίσουμε διακριτές ομάδες (clusters) πελατών με βάση τα χαρακτηριστικά τους, ώστε να μπορούν να σχεδιαστούν στοχευμένες στρατηγικές Marketing.
Το dataset περιλαμβάνει 200 παρατηρήσεις και τις εξής μεταβλητές:
CustomerID, Gender (Φύλο), Age
(Ηλικία), Annual Income (Ετήσιο Εισόδημα σε χιλιάδες
δολάρια) και Spending Score (Ένα σκορ από 1-100 που δείχνει
πόσο συχνά και πόσα χρήματα ξοδεύει ο πελάτης).
#Φόρτωση του dataset
library(readr)
mall_customers <- read_csv("C://Users/gourg/Downloads/archive (1)/Mall_customers.csv")
## Rows: 200 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): Gender
## dbl (4): CustomerID, Age, Annual Income (k$), Spending Score (1-100)
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#Επισκόπηση των πρώτων γραμμών
head(mall_customers)
## # A tibble: 6 × 5
## CustomerID Gender Age `Annual Income (k$)` `Spending Score (1-100)`
## <dbl> <chr> <dbl> <dbl> <dbl>
## 1 1 Male 19 15 39
## 2 2 Male 21 15 81
## 3 3 Female 20 16 6
## 4 4 Female 23 16 77
## 5 5 Female 31 17 40
## 6 6 Female 22 17 76
#Περιγραφικά στατιστικά
summary(mall_customers)
## CustomerID Gender Age Annual Income (k$)
## Min. : 1.00 Length:200 Min. :18.00 Min. : 15.00
## 1st Qu.: 50.75 Class :character 1st Qu.:28.75 1st Qu.: 41.50
## Median :100.50 Mode :character Median :36.00 Median : 61.50
## Mean :100.50 Mean :38.85 Mean : 60.56
## 3rd Qu.:150.25 3rd Qu.:49.00 3rd Qu.: 78.00
## Max. :200.00 Max. :70.00 Max. :137.00
## Spending Score (1-100)
## Min. : 1.00
## 1st Qu.:34.75
## Median :50.00
## Mean :50.20
## 3rd Qu.:73.00
## Max. :99.00
Για τους αλγόριθμους συσταδοποίησης (που βασίζονται στον υπολογισμό αποστάσεων) θα κρατήσουμε μόνο τις αριθμητικές μεταβλητές: Ηλικία, Εισόδημα και Σκορ Αγορών. Το ID του πελάτη και το φύλο θα αφαιρεθούν. Στη συνέχεια, θα τυποποιήσουμε (scale) τα δεδομένα ώστε όλες οι μεταβλητές να έχουν ίση βαρύτητα στον υπολογισμό της απόστασης.
# Κρατάμε τις στήλες Age (3), Annual Income (4) και Spending Score (5)
df <- mall_customers[, 3:5]
# Μετονομάζουμε τις στήλες για μεγαλύτερη ευκολία στον κώδικα
colnames(df) <- c("Age", "AnnualIncome", "SpendingScore")
# Τυποποίηση (Z-score standardization)
df_scaled <- scale(df)
# Προβολή των πρώτων γραμμών μετά την τυποποίηση
head(df_scaled)
## Age AnnualIncome SpendingScore
## [1,] -1.4210029 -1.734646 -0.4337131
## [2,] -1.2778288 -1.734646 1.1927111
## [3,] -1.3494159 -1.696572 -1.7116178
## [4,] -1.1346547 -1.696572 1.0378135
## [5,] -0.5619583 -1.658498 -0.3949887
## [6,] -1.2062418 -1.658498 0.9990891
Για την ιεραρχική συσταδοποίηση, υπολογίζουμε τη μήτρα των
Ευκλείδειων αποστάσεων και χρησιμοποιούμε τη μέθοδο
Ward.D2, η οποία δημιουργεί συμπαγείς και σφαιρικές
συστάδες ελαχιστοποιώντας τη διακύμανση μέσα στα clusters.
# Υπολογισμός Μήτρας Αποστάσεων
dist_matrix <- dist(df_scaled, method = "euclidean")
# Εφαρμογή της μεθόδου Ward
hc <- hclust(dist_matrix, method = "ward.D2")
# Δημιουργία Δενδρογράμματος
plot(hc, cex = 0.6, hang = -1,
main = "Δενδρόγραμμα Ιεραρχικής Συσταδοποίησης Πελατών",
xlab = "Πελάτες", ylab = "Απόσταση (Height)")
# Βλέποντας το δενδρόγραμμα, το κόβουμε σε 5 συστάδες (k=5)
# καθώς φαίνεται να προσφέρει τον βέλτιστο διαχωρισμό.
rect.hclust(hc, k = 5, border = c("red", "blue", "green", "purple", "orange"))
# Αποθήκευση του cluster στο οποίο ανήκει η κάθε παρατήρηση
hc_clusters <- cutree(hc, k = 5)
Εφαρμόζουμε και τον αλγόριθμο K-Means. Επιλέγουμε πάλι 5 συστάδες (k=5) για να συγκρίνουμε τα αποτελέσματα. Στη συνέχεια, θα οπτικοποιήσουμε τις συστάδες συγκρίνοντας το Ετήσιο Εισόδημα με το Σκορ Αγορών.
# Ορίζουμε το seed που επιλέχθηκε
set.seed(1926)
# Εφαρμογή K-Means με 5 κέντρα
km_res <- kmeans(df_scaled, centers = 5, nstart = 25)
# Υπολογισμός των μέσων όρων (πριν μετατρέψουμε το cluster σε factor)
cluster_profiles <- aggregate(df[, c("Age", "AnnualIncome", "SpendingScore")],
by = list(Cluster = km_res$cluster),
FUN = mean)
# Εκτύπωση των προφίλ των συστάδων (Τώρα η στρογγυλοποίηση θα δουλέψει τέλεια)
print(round(cluster_profiles, 1))
## Cluster Age AnnualIncome SpendingScore
## 1 1 39.9 86.1 19.4
## 2 2 55.6 54.4 48.9
## 3 3 32.9 86.1 81.5
## 4 4 25.2 41.1 62.2
## 5 5 46.2 26.8 18.4
# Ενσωμάτωση των clusters πίσω στο αρχικό dataset ως κατηγορία (factor) για το γράφημα
df$Cluster <- as.factor(km_res$cluster)
# Οπτικοποίηση: Εισόδημα vs Σκορ Αγορών
plot(df$AnnualIncome, df$SpendingScore,
col = df$Cluster,
main = "Συστάδες Πελατών (K-Means) - Εισόδημα vs Σκορ",
pch = 19, cex = 1.5,
xlab = "Ετήσιο Εισόδημα (k$)",
ylab = "Σκορ Αγορών (1-100)")
legend("topright", legend = paste("Cluster", 1:5),
col = 1:5, pch = 19, title = "Συστάδες")
Μελετώντας τόσο το γράφημα όσο και τον παραπάνω πίνακα μέσων όρων (cluster profiles), ταυτοποιούμε 5 ξεκάθαρα τμήματα πελατών (Market Segments). Βλέποντας τα μέσα επίπεδα Εισοδήματος (AnnualIncome) και Σκορ (SpendingScore) για την κάθε ομάδα (Cluster 1-5), προκύπτουν τα εξής προφίλ:
Τελικό Σχόλιο: Η χρήση της συσταδοποίησης απέδειξε πώς τα δεδομένα μπορούν να μετατραπούν σε στοχευμένες επιχειρηματικές αποφάσεις, επιτρέποντας στη διοίκηση να αποφύγει τις γενικές “one-size-fits-all” προσεγγίσεις στο Marketing.