#Περιγραφή Dataset
Εισαγωγή και Εξήγηση του Dataset Το dataset Online Retail II UCI περιέχει δεδομένα συναλλαγών από ένα ηλεκτρονικό κατάστημα με έδρα το Ηνωμένο Βασίλειο, για την περίοδο από 01/12/2009 έως 09/12/2011. Το κατάστημα πωλεί κυρίως μοναδικά δώρα για όλες τις περιστάσεις, και πολλοί από τους πελάτες του είναι χονδρέμποροι. Το dataset περιλαμβάνει 1.067.371 εγγραφές (συναλλαγές) και 8 στήλες:
InvoiceNo: Αριθμός τιμολογίου (6ψήφιος, μοναδικός για κάθε συναλλαγή. Αν αρχίζει με 'C', υποδηλώνει ακύρωση).
StockCode: Κωδικός προϊόντος (5ψήφιος, μοναδικός για κάθε προϊόν).
Description: Περιγραφή προϊόντος.
Quantity: Ποσότητα προϊόντος ανά συναλλαγή.
InvoiceDate: Ημερομηνία και ώρα συναλλαγής.
UnitPrice: Τιμή μονάδας προϊόντος (σε λίρες Αγγλίας).
CustomerID: Αναγνωριστικό πελάτη (5ψήφιος, μοναδικός για κάθε πελάτη).
Country: Χώρα διαμονής του πελάτη.
Το dataset είναι διαθέσιμο από το Kaggle: Online Retail II UCI.
#Στόχος Ανάλυσης
Θα εφαρμόσουμε ιεραρχική συσταδοποίηση και K-means συσταδοποίηση για να κατηγοριοποιήσουμε τους πελάτες με βάση:
Recency (R): Πόσες ημέρες έχουν περάσει από την τελευταία αγορά του πελάτη.
Frequency (F): Πόσες φορές έχει αγοράσει ο πελάτης.
Monetary (M): Συνολική δαπάνη του πελάτη.
Αυτά τα χαρακτηριστικά θα χρησιμοποιηθούν για τη δημιουργία ομάδων πελατών με παρόμοια αγοραστική συμπεριφορά.
#Φόρτωση και Καθαρισμός Δεδομένων Αρχικά, φορτώνουμε το dataset και αφαιρούμε ακυρώσεις (InvoiceNo που αρχίζει με ‘C’), μη έγκυρα δεδομένα (αρνητικές ποσότητες ή τιμές), και ελλιπή δεδομένα (κενά CustomerID).
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(lubridate)
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
library(ggplot2)
library(cluster)
library(factoextra)
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
data <- read.csv("C:/Users/Tasos/Downloads/online_retail_II.csv")
data <- data %>%
filter(!grepl("^C", Invoice)) %>% # Αφαίρεση ακυρώσεων
filter(Quantity > 0, Price > 0) %>% # Αφαίρεση αρνητικών/μηδενικών τιμών
filter(!is.na(Customer.ID)) # Αφαίρεση κενών CustomerID
data$InvoiceDate <- as.POSIXct(data$InvoiceDate, format="%Y-%m-%d %H:%M:%S")
#Δημιουργούμε των ομάδων ανά πελάτη:
Recency: Ημέρες από την τελευταία αγορά μέχρι την πιο πρόσφατη ημερομηνία στο dataset. Frequency: Αριθμός συναλλαγών ανά πελάτη. Monetary: Συνολική δαπάνη (Quantity * UnitPrice).
max_date <- max(data$InvoiceDate) + days(1)
rfm_data <- data %>% group_by(Customer.ID) %>%
summarise(
Recency = as.numeric(difftime(max_date, max(InvoiceDate), units="days")),
Frequency = n(),
Monetary = sum(Quantity * Price)
)
rfm_scaled <- scale(rfm_data[, c("Recency", "Frequency", "Monetary")])
#Ιεραρχική Συσταδοποίηση
dist_matrix <- dist(rfm_scaled, method="euclidean")
hc <- hclust(dist_matrix, method="ward.D2")
plot(hc, main="Dendrogram of Hierarchical Clustering", xlab="", sub="", cex=0.6)
rfmclusters <- cutree(hc, k=4)
rfm_data$HC_Cluster <- rfmclusters
#Οπτικοποίηση Ιεραρχικής Συσταδοποίησης
fviz_cluster(list(data=rfm_scaled, cluster=rfmclusters), geom="point", main="Hierarchical Clustering")
#K-means Συσταδοποίηση
fviz_nbclust(rfm_scaled, kmeans, method="wss") +
labs(title="Elbow Method for K-means")
set.seed(022)
kmeans_rfm <- kmeans(rfm_scaled, centers=4, nstart=25)
rfm_data$Kmeans_Cluster <- kmeans_rfm$cluster
#Οπτικοποίηση K-means Συσταδοποίησης
fviz_cluster(kmeans_rfm, data=rfm_scaled, geom="point", main="K-means Clustering")
##Σύγκριση Αποτελεσμάτων
Περιγραφή Συστάδων
hc_summary <- rfm_data %>%
group_by(HC_Cluster) %>%
summarise(
Avg_Recency = mean(Recency),
Avg_Frequency = mean(Frequency),
Avg_Monetary = mean(Monetary),
Count = n()
)
print("Hierarchical Clustering Summary:")
## [1] "Hierarchical Clustering Summary:"
print(hc_summary)
## # A tibble: 4 × 5
## HC_Cluster Avg_Recency Avg_Frequency Avg_Monetary Count
## <int> <dbl> <dbl> <dbl> <int>
## 1 1 86.4 155. 2994. 4201
## 2 2 499. 40.4 727. 1651
## 3 3 23.0 3380. 117785. 24
## 4 4 1.53 2454. 568712. 2
kmeans_summary <- rfm_data %>%
group_by(Kmeans_Cluster) %>%
summarise(
Avg_Recency = mean(Recency),
Avg_Frequency = mean(Frequency),
Avg_Monetary = mean(Monetary),
Count = n()
)
print("K-means Clustering Summary:")
## [1] "K-means Clustering Summary:"
print(kmeans_summary)
## # A tibble: 4 × 5
## Kmeans_Cluster Avg_Recency Avg_Frequency Avg_Monetary Count
## <int> <dbl> <dbl> <dbl> <int>
## 1 1 74.8 114. 2168. 3652
## 2 2 471. 43.1 759. 1921
## 3 3 3.46 4896. 217186. 13
## 4 4 26.6 827. 18985. 292
#Συμπεράσματα Ιεραρχική Συσταδοποίηση: Παράγει ένα δενδρόγραμμα που επιτρέπει την κατανόηση της ιεραρχικής δομής των δεδομένων. Είναι χρήσιμη για την κατανόηση της σχέσης μεταξύ των συστάδων. K-means Συσταδοποίηση: Είναι ταχύτερη και πιο κατάλληλη για μεγάλα datasets, αλλά απαιτεί προκαθορισμό του αριθμού των συστάδων (k). Σύγκριση: Ο δείκτης Rand δείχνει το επίπεδο συμφωνίας μεταξύ των δύο μεθόδων. Τυπικά, τιμές κοντά στο 1 υποδηλώνουν υψηλή ομοιότητα. Οι διαφορές στα προφίλ των συστάδων μπορεί να οφείλονται στην ευαισθησία της K-means σε αρχικές συνθήκες ή στη μέθοδο συσσωμάτωσης της ιεραρχικής.
Η επιλογή μεταξύ των δύο μεθόδων εξαρτάται από τον σκοπό της ανάλυσης. Αν θέλουμε να εξερευνήσουμε την ιεραρχική δομή, η ιεραρχική συσταδοποίηση είναι προτιμότερη. Αν χρειαζόμαστε γρήγορα και καθαρά αποτελέσματα, η K-means είναι πιο πρακτική.