Studi Kasus Database Sakila — Toko Rental DVD
Database Sakila merupakan contoh database relasional yang dikembangkan oleh MySQL, merepresentasikan sistem informasi toko rental DVD. Analisis ini bertujuan untuk mengeksplorasi dua insight utama: (1) tren dan perbandingan revenue antar toko, serta (2) segmentasi pelanggan berdasarkan perilaku transaksi menggunakan metode K-Means Clustering.
Analisis ini memiliki empat tujuan utama:
Analisis ini dilakukan melalui beberapa tahapan yang sistematis, yaitu:
library(RMySQL)
library(DBI)
library(dplyr)
library(ggplot2)
library(lubridate)
library(scales)
library(cluster)
library(factoextra)
library(knitr)
library(kableExtra)con <- dbConnect(
RMySQL::MySQL(),
dbname = "sakila",
host = "127.0.0.1",
port = 3306,
user = "root",
password = "nasipadanggg"
)
dbListTables(con)## [1] "actor" "actor_info"
## [3] "address" "category"
## [5] "city" "country"
## [7] "customer" "customer_list"
## [9] "film" "film_actor"
## [11] "film_category" "film_list"
## [13] "film_text" "inventory"
## [15] "language" "nicer_but_slower_film_list"
## [17] "payment" "rental"
## [19] "sales_by_film_category" "sales_by_store"
## [21] "staff" "staff_list"
## [23] "store"
Tiga dataset utama diambil langsung dari database Sakila menggunakan
query SQL. Dataset pertama berisi agregasi revenue per bulan
(df_revenue), dataset kedua memisahkan revenue per toko per
bulan (df_toko), dan dataset ketiga mengambil data perilaku
transaksi per pelanggan sebagai bahan segmentasi
(df_customer).
# ── 1. Revenue per bulan ──────────────────────────────────────────
df_revenue <- dbGetQuery(con, "
SELECT
DATE_FORMAT(payment_date, '%Y-%m') AS bulan,
SUM(amount) AS total_revenue,
COUNT(payment_id) AS jumlah_transaksi
FROM payment
GROUP BY bulan
ORDER BY bulan;
")
# ── 2. Revenue per toko per bulan ─────────────────────────────────
df_toko <- dbGetQuery(con, "
SELECT
DATE_FORMAT(p.payment_date, '%Y-%m') AS bulan,
s.store_id,
SUM(p.amount) AS total_revenue,
COUNT(p.payment_id) AS jumlah_transaksi
FROM payment p
JOIN rental r ON p.rental_id = r.rental_id
JOIN inventory i ON r.inventory_id = i.inventory_id
JOIN store s ON i.store_id = s.store_id
GROUP BY bulan, s.store_id
ORDER BY bulan, s.store_id;
")
# ── 3. Segmentasi pelanggan ───────────────────────────────────────
df_customer <- dbGetQuery(con, "
SELECT
p.customer_id,
CONCAT(c.first_name, ' ', c.last_name) AS nama,
COUNT(p.payment_id) AS frekuensi,
SUM(p.amount) AS total_spending,
MAX(p.payment_date) AS last_payment
FROM payment p
JOIN customer c ON p.customer_id = c.customer_id
GROUP BY p.customer_id, nama
ORDER BY total_spending DESC;
")
head(df_revenue)## bulan total_revenue jumlah_transaksi
## 1 2005-05 4823.44 1156
## 2 2005-06 9629.89 2311
## 3 2005-07 28368.91 6709
## 4 2005-08 24070.14 5686
## 5 2006-02 514.18 182
## bulan store_id total_revenue jumlah_transaksi
## 1 2005-05 1 2459.25 575
## 2 2005-05 2 2364.19 581
## 3 2005-06 1 4734.79 1121
## 4 2005-06 2 4895.10 1190
## 5 2005-07 1 14308.66 3334
## 6 2005-07 2 14060.25 3375
## customer_id nama frekuensi total_spending last_payment
## 1 526 KARL SEAL 45 221.55 2005-08-23 22:21:03
## 2 148 ELEANOR HUNT 46 216.54 2005-08-23 05:57:04
## 3 144 CLARA SHAW 42 195.58 2005-08-23 12:43:30
## 4 137 RHONDA KENNEDY 39 194.61 2005-08-23 21:56:04
## 5 178 MARION SNYDER 39 194.61 2006-02-14 15:16:03
## 6 459 TOMMY COLLAZO 38 186.62 2005-08-23 14:52:50
Sebelum preprocessing, dilakukan pengecekan kualitas data mencakup missing values, duplikasi, tipe data, nilai tidak wajar, dan outlier pada ketiga dataset.
# ── 1. Missing Values ─────────────────────────────────────────────
bind_rows(
df_revenue %>% summarise(across(everything(), ~sum(is.na(.)))) %>% mutate(dataset = "df_revenue"),
df_toko %>% summarise(across(everything(), ~sum(is.na(.)))) %>% mutate(dataset = "df_toko"),
df_customer %>% summarise(across(everything(), ~sum(is.na(.)))) %>% mutate(dataset = "df_customer")
) %>% select(dataset, everything()) %>%
kable(caption = "Pengecekan Missing Values") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)| dataset | bulan | total_revenue | jumlah_transaksi | store_id | customer_id | nama | frekuensi | total_spending | last_payment |
|---|---|---|---|---|---|---|---|---|---|
| df_revenue | 0 | 0 | 0 | NA | NA | NA | NA | NA | NA |
| df_toko | 0 | 0 | 0 | 0 | NA | NA | NA | NA | NA |
| df_customer | NA | NA | NA | NA | 0 | 0 | 0 | 0 | 0 |
# ── 2. Duplikasi ──────────────────────────────────────────────────
data.frame(
Dataset = c("df_revenue", "df_toko", "df_customer"),
Duplikasi = c(sum(duplicated(df_revenue)),
sum(duplicated(df_toko)),
sum(duplicated(df_customer)))
) %>%
kable(caption = "Pengecekan Duplikasi") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)| Dataset | Duplikasi |
|---|---|
| df_revenue | 0 |
| df_toko | 0 |
| df_customer | 0 |
# ── 3. Nilai Tidak Wajar ──────────────────────────────────────────
data.frame(
Variabel = c("total_revenue", "jumlah_transaksi", "total_spending", "frekuensi"),
Nilai_Negatif = c(sum(df_revenue$total_revenue <= 0),
sum(df_revenue$jumlah_transaksi <= 0),
sum(df_customer$total_spending <= 0),
sum(df_customer$frekuensi <= 0))
) %>%
kable(caption = "Pengecekan Nilai Tidak Wajar") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)| Variabel | Nilai_Negatif |
|---|---|
| total_revenue | 0 |
| jumlah_transaksi | 0 |
| total_spending | 0 |
| frekuensi | 0 |
# ── 4. Outlier (IQR Method) ───────────────────────────────────────
outlier_df <- function(x, nama) {
Q1 <- quantile(x, 0.25)
Q3 <- quantile(x, 0.75)
IQR_val <- Q3 - Q1
batas_bawah <- Q1 - 1.5 * IQR_val
batas_atas <- Q3 + 1.5 * IQR_val
data.frame(
Variabel = nama,
Q1 = round(Q1, 2),
Q3 = round(Q3, 2),
Batas_Bawah = round(batas_bawah, 2),
Batas_Atas = round(batas_atas, 2),
Jumlah_Outlier = sum(x < batas_bawah | x > batas_atas)
)
}
bind_rows(
outlier_df(df_customer$frekuensi, "frekuensi"),
outlier_df(df_customer$total_spending, "total_spending")
) %>%
kable(caption = "Pengecekan Outlier (Metode IQR)") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)| Variabel | Q1 | Q3 | Batas_Bawah | Batas_Atas | Jumlah_Outlier | |
|---|---|---|---|---|---|---|
| 25%…1 | frekuensi | 23.00 | 30.0 | 12.50 | 40.50 | 6 |
| 25%…2 | total_spending | 94.78 | 128.7 | 43.91 | 179.58 | 6 |
# ── 5. Dimensi Data ───────────────────────────────────────────────
data.frame(
Dataset = c("df_revenue", "df_toko", "df_customer"),
Baris = c(nrow(df_revenue), nrow(df_toko), nrow(df_customer)),
Kolom = c(ncol(df_revenue), ncol(df_toko), ncol(df_customer))
) %>%
kable(caption = "Dimensi Dataset") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)| Dataset | Baris | Kolom |
|---|---|---|
| df_revenue | 5 | 3 |
| df_toko | 10 | 4 |
| df_customer | 599 | 5 |
Berdasarkan hasil EDA, diperoleh beberapa temuan penting.
Missing values tidak ditemukan pada ketiga dataset,
menunjukkan bahwa data dari database Sakila sudah lengkap.
Duplikasi juga tidak ditemukan, artinya setiap baris
merupakan record yang unik. Dari sisi tipe data, kolom
bulan dan last_payment masih bertipe
character dan akan dikonversi pada tahap preprocessing.
Nilai tidak wajar seperti angka negatif tidak ditemukan
pada seluruh variabel numerik. Terkait outlier,
ditemukan masing-masing 6 outlier pada variabel frekuensi
dan total_spending menggunakan metode IQR dengan batas
\(Q3 + 1.5 \times IQR\). Outlier ini
tidak dihapus karena merepresentasikan pelanggan dengan
aktivitas sangat tinggi yang justru relevan untuk analisis
segmentasi.
Kolom bulan dikonversi ke format Date,
store_id diubah menjadi faktor berlabel, dan
last_payment dikonversi ke POSIXct. Variabel
recency dihitung sebagai selisih hari dari transaksi
terakhir pelanggan ke tanggal transaksi terbaru dalam data. Ketiga
variabel clustering kemudian dinormalisasi menggunakan
scale() agar tidak ada variabel yang mendominasi karena
perbedaan skala.
# ── 1. Revenue per bulan ──────────────────────────────────────────
df_revenue <- df_revenue %>%
mutate(
bulan = as.Date(paste0(bulan, "-01")),
rata_transaksi = total_revenue / jumlah_transaksi
)
# ── 2. Data toko ──────────────────────────────────────────────────
df_toko <- df_toko %>%
mutate(
bulan = as.Date(paste0(bulan, "-01")),
store_id = factor(store_id, labels = c("Store 1", "Store 2"))
)
# ── 3. Data customer ──────────────────────────────────────────────
df_customer <- df_customer %>%
mutate(last_payment = as.POSIXct(last_payment))
tgl_max <- max(df_customer$last_payment)
df_customer <- df_customer %>%
mutate(
recency = as.numeric(difftime(tgl_max, last_payment, units = "days"))
)
# ── 4. Normalisasi untuk clustering ──────────────────────────────
df_cluster <- df_customer %>%
select(frekuensi, total_spending, recency) %>%
scale() %>%
as.data.frame()
glimpse(df_customer)## Rows: 599
## Columns: 6
## $ customer_id <dbl> 526, 148, 144, 137, 178, 459, 469, 468, 236, 181, 176, …
## $ nama <chr> "KARL SEAL", "ELEANOR HUNT", "CLARA SHAW", "RHONDA KENN…
## $ frekuensi <dbl> 45, 46, 42, 39, 39, 38, 40, 39, 42, 34, 37, 35, 32, 33,…
## $ total_spending <dbl> 221.55, 216.54, 195.58, 194.61, 194.61, 186.62, 177.60,…
## $ last_payment <dttm> 2005-08-23 22:21:03, 2005-08-23 05:57:04, 2005-08-23 1…
## $ recency <dbl> 174.7049, 175.3882, 175.1059, 174.7222, 0.0000, 175.016…
## frekuensi total_spending recency
## Min. :-2.8931 Min. :-2.43169 Min. :-1.6692
## 1st Qu.:-0.7406 1st Qu.:-0.69964 1st Qu.:-1.6692
## Median :-0.1535 Median :-0.07103 Median : 0.5905
## Mean : 0.0000 Mean : 0.00000 Mean : 0.0000
## 3rd Qu.: 0.6292 3rd Qu.: 0.63760 3rd Qu.: 0.5992
## Max. : 3.7601 Max. : 4.29784 Max. : 0.6756
Setelah preprocessing, kolom bulan berhasil dikonversi
ke format Date dan store_id menjadi faktor
berlabel. Variabel recency berhasil dihitung dengan rentang
0 hingga 181,6 hari. Hasil summary(df_cluster) menunjukkan
ketiga variabel sudah ternormalisasi dengan mean = 0 dan skala yang
sebanding, sehingga proses clustering tidak akan didominasi oleh satu
variabel tertentu.
Tiga visualisasi dibuat untuk mengeksplorasi data secara visual. Line chart digunakan untuk melihat tren revenue dari waktu ke waktu. Bar chart grouped digunakan untuk membandingkan kontribusi revenue Store 1 vs Store 2 per bulan. Scatter plot dengan garis regresi digunakan untuk melihat pola hubungan antara frekuensi rental dan total spending pelanggan.
ggplot(df_revenue, aes(x = bulan, y = total_revenue)) +
geom_line(color = "#2196F3", linewidth = 1.2) +
geom_point(color = "#2196F3", size = 3) +
geom_label(aes(label = dollar(total_revenue, prefix = "$")),
vjust = -0.5, size = 3.2, fill = "white", color = "#2196F3") +
scale_y_continuous(labels = dollar_format(prefix = "$")) +
scale_x_date(date_labels = "%b %Y", date_breaks = "1 month") +
labs(
title = "Tren Total Revenue per Bulan",
subtitle = "Database Sakila — Mei 2005 s/d Februari 2006",
x = "Bulan",
y = "Total Revenue (USD)",
caption = "Sumber: Database Sakila"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(color = "gray50"),
axis.text.x = element_text(angle = 45, hjust = 1)
)Tren Revenue per Bulan
Revenue mengalami pertumbuhan yang sangat pesat dari Mei 2005 ($4.823) hingga mencapai puncaknya pada Juli 2005 ($28.369). Setelah itu terjadi penurunan pada Agustus 2005 ($24.070), kemudian terdapat gap transaksi yang panjang hingga Februari 2006 di mana revenue anjlok drastis menjadi hanya $514. Pola ini mengindikasikan adanya gangguan operasional atau perubahan sistem pencatatan pada periode tersebut yang perlu diinvestigasi lebih lanjut.
ggplot(df_toko, aes(x = bulan, y = total_revenue, fill = store_id)) +
geom_bar(stat = "identity", position = "dodge", width = 20) +
scale_y_continuous(labels = dollar_format(prefix = "$")) +
scale_x_date(date_labels = "%b %Y", date_breaks = "1 month") +
scale_fill_manual(values = c("Store 1" = "#4CAF50", "Store 2" = "#FF9800")) +
labs(
title = "Perbandingan Revenue per Toko per Bulan",
subtitle = "Store 1 vs Store 2",
x = "Bulan",
y = "Total Revenue (USD)",
fill = "Toko",
caption = "Sumber: Database Sakila"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(color = "gray50"),
axis.text.x = element_text(angle = 45, hjust = 1)
)Perbandingan Revenue per Toko
Perbandingan antara Store 1 dan Store 2 menunjukkan performa yang relatif seimbang di setiap bulannya. Tidak ada satu toko pun yang secara konsisten mendominasi revenue secara signifikan. Pada Mei–Juni 2005 Store 2 sedikit lebih unggul, namun pada Juli 2005 Store 1 memimpin tipis. Keseimbangan ini mengindikasikan bahwa kedua toko beroperasi dengan kapasitas dan basis pelanggan yang setara.
ggplot(df_customer, aes(x = frekuensi, y = total_spending)) +
geom_point(alpha = 0.5, color = "#9C27B0", size = 2) +
geom_smooth(method = "lm", color = "#F44336", se = TRUE) +
scale_y_continuous(labels = dollar_format(prefix = "$")) +
labs(
title = "Hubungan Frekuensi Rental vs Total Spending Pelanggan",
subtitle = "599 pelanggan — Database Sakila",
x = "Frekuensi Rental",
y = "Total Spending (USD)",
caption = "Sumber: Database Sakila"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(color = "gray50")
)Hubungan Frekuensi Rental vs Total Spending
Scatter plot menunjukkan pola hubungan linear positif yang kuat antara frekuensi rental dan total spending. Titik-titik data tersebar cukup rapat di sekitar garis regresi, mengindikasikan bahwa semakin sering pelanggan menyewa, semakin besar pula total pengeluarannya. Hal ini akan dikonfirmasi secara statistik pada analisis regresi berikutnya.
## total_revenue jumlah_transaksi rata_transaksi
## Min. : 514.2 Min. : 182 Min. :2.825
## 1st Qu.: 4823.4 1st Qu.:1156 1st Qu.:4.167
## Median : 9629.9 Median :2311 Median :4.173
## Mean :13481.3 Mean :3209 Mean :3.925
## 3rd Qu.:24070.1 3rd Qu.:5686 3rd Qu.:4.228
## Max. :28368.9 Max. :6709 Max. :4.233
## frekuensi total_spending recency
## Min. :12.00 Min. : 50.85 Min. : 0.0
## 1st Qu.:23.00 1st Qu.: 94.78 1st Qu.: 0.0
## Median :26.00 Median :110.73 Median :175.0
## Mean :26.78 Mean :112.53 Mean :129.3
## 3rd Qu.:30.00 3rd Qu.:128.71 3rd Qu.:175.7
## Max. :46.00 Max. :221.55 Max. :181.6
Statistik deskriptif menunjukkan bahwa revenue bulanan sangat bervariasi, berkisar antara $514 hingga $28.369, dengan rata-rata $13.481 per bulan. Rata-rata nilai per transaksi relatif stabil di kisaran $3,9–$4,2, menunjukkan harga sewa per unit tidak fluktuatif. Dari sisi pelanggan, rata-rata frekuensi rental adalah 26–27 kali dengan total spending rata-rata $112,53. Variabel recency terbagi dalam dua kelompok jelas yaitu pelanggan dengan recency 0 hari (aktif di Februari 2006) dan sekitar 175 hari (terakhir aktif Agustus 2005), menunjukkan adanya gap aktivitas yang signifikan.
Regresi linear sederhana digunakan untuk menguji apakah frekuensi rental berpengaruh signifikan terhadap total spending pelanggan. Model yang digunakan adalah:
\[\hat{Y} = \beta_0 + \beta_1 X + \varepsilon\]
Di mana:
##
## Call:
## lm(formula = total_spending ~ frekuensi, data = df_customer)
##
## Residuals:
## Min 1Q Median 3Q Max
## -41.386 -8.391 -0.074 8.431 41.936
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -3.22174 2.72462 -1.182 0.237
## frekuensi 4.32164 0.09992 43.249 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 12.49 on 597 degrees of freedom
## Multiple R-squared: 0.7581, Adjusted R-squared: 0.7577
## F-statistic: 1871 on 1 and 597 DF, p-value: < 2.2e-16
Persamaan regresi yang dihasilkan adalah \(\hat{Y} = -3{,}22 + 4{,}32X\). Hasil analisis regresi menunjukkan beberapa temuan penting. Pertama, koefisien frekuensi (\(\beta_1 = 4{,}32\)) bermakna bahwa setiap penambahan 1 kali rental, total spending pelanggan meningkat rata-rata sebesar $4,32. Kedua, intercept (\(\beta_0 = -3{,}22\), \(p = 0{,}237\)) tidak signifikan secara statistik, yang wajar karena pelanggan dengan frekuensi 0 memang tidak memiliki spending. Ketiga, p-value untuk koefisien frekuensi sangat kecil (\(< 2{,}2 \times 10^{-16}\)), membuktikan bahwa frekuensi rental berpengaruh sangat signifikan terhadap total spending. Keempat, nilai R-squared sebesar 0,7581 menunjukkan bahwa 75,81% variasi total spending dapat dijelaskan oleh frekuensi rental — hubungan yang sangat kuat secara statistik.
K-Means Clustering digunakan untuk mengelompokkan pelanggan berdasarkan tiga variabel: frekuensi rental, total spending, dan recency. Fungsi objektif yang diminimalkan adalah:
\[J = \sum_{k=1}^{K} \sum_{x_i \in C_k} \| x_i - \mu_k \|^2\]
Di mana:
set.seed(42)
wss <- sapply(1:8, function(k) {
kmeans(df_cluster, centers = k, nstart = 25)$tot.withinss
})
elbow_df <- data.frame(k = 1:8, wss = wss)
ggplot(elbow_df, aes(x = k, y = wss)) +
geom_line(color = "#2196F3", linewidth = 1.2) +
geom_point(color = "#2196F3", size = 3) +
geom_vline(xintercept = 3, linetype = "dashed", color = "#F44336") +
scale_x_continuous(breaks = 1:8) +
labs(
title = "Elbow Method — Penentuan Jumlah Cluster Optimal",
subtitle = "Garis merah = jumlah cluster yang dipilih (K=3)",
x = "Jumlah Cluster (K)",
y = "Total Within-Cluster Sum of Squares (WSS)",
caption = "Sumber: Database Sakila"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(color = "gray50")
)Elbow Method
Grafik Elbow Method menunjukkan bahwa penurunan nilai WSS mulai melandai secara signifikan setelah K=3. Penambahan cluster di atas 3 tidak memberikan pengurangan WSS yang berarti, sehingga K=3 dipilih sebagai jumlah cluster optimal.
set.seed(42)
kmeans_result <- kmeans(df_cluster, centers = 3, nstart = 25)
df_customer$cluster <- factor(kmeans_result$cluster,
labels = c("Bronze", "Silver", "Gold"))
fviz_cluster(kmeans_result,
data = df_cluster,
geom = "point",
ellipse = TRUE,
ellipse.type = "convex",
palette = c("#CD7F32", "#C0C0C0", "#FFD700"),
ggtheme = theme_minimal(),
main = "Segmentasi Pelanggan — K-Means Clustering (K=3)")Hasil K-Means Clustering
df_customer %>%
group_by(cluster) %>%
summarise(
jumlah_pelanggan = n(),
rata_frekuensi = round(mean(frekuensi), 2),
rata_spending = round(mean(total_spending), 2),
rata_recency = round(mean(recency), 2)
) %>%
kable(
caption = "Ringkasan Statistik per Cluster",
col.names = c("Cluster", "Jumlah Pelanggan", "Rata-rata Frekuensi",
"Rata-rata Spending ($)", "Rata-rata Recency (hari)")
) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| Cluster | Jumlah Pelanggan | Rata-rata Frekuensi | Rata-rata Spending ($) | Rata-rata Recency (hari) |
|---|---|---|---|---|
| Bronze | 146 | 26.84 | 109.19 | 0.0 |
| Silver | 252 | 22.98 | 95.32 | 175.7 |
| Gold | 201 | 31.51 | 136.54 | 165.0 |
Hasil K-Means Clustering dengan K=3 berhasil mengelompokkan 599 pelanggan ke dalam tiga segmen dengan karakteristik perilaku transaksi yang berbeda-beda.
🥉 Segmen Bronze (146 pelanggan) terdiri dari pelanggan dengan rata-rata frekuensi rental 26,84 kali dan total spending rata-rata $109,19. Yang paling menonjol adalah nilai recency sebesar 0 hari, yang berarti seluruh pelanggan dalam kelompok ini melakukan transaksi terakhirnya pada Februari 2006 — periode paling akhir dalam data. Dengan kata lain, Bronze adalah satu-satunya segmen yang masih aktif saat data diambil. Meski demikian, frekuensi dan spending-nya berada di posisi menengah, mengindikasikan bahwa pelanggan Bronze adalah tipe pelanggan kasual yang kembali aktif namun belum menunjukkan komitmen transaksi yang tinggi.
🥈 Segmen Silver (252 pelanggan) merupakan kelompok terbesar dengan jumlah 252 pelanggan atau sekitar 42% dari total pelanggan. Rata-rata frekuensi rental hanya 22,98 kali dengan total spending rata-rata $95,32 — keduanya merupakan nilai terendah di antara ketiga segmen. Nilai recency sebesar 175,7 hari menunjukkan pelanggan Silver terakhir bertransaksi sekitar Agustus 2005, yang berarti sudah hampir 6 bulan tidak aktif. Kombinasi frekuensi rendah, spending rendah, dan recency tinggi menjadikan Silver sebagai segmen pelanggan yang berisiko churn atau bahkan sudah churn. Meskipun demikian, karena jumlahnya paling besar, segmen ini menyimpan potensi revenue yang signifikan jika berhasil direaktivasi.
🥇 Segmen Gold (201 pelanggan) memiliki rata-rata frekuensi rental tertinggi sebesar 31,51 kali dan rata-rata total spending tertinggi sebesar $136,54, menjadikannya segmen paling bernilai secara bisnis. Recency rata-rata 165,0 hari menunjukkan transaksi terakhir sekitar Agustus 2005 — tidak aktif dalam periode terkini, namun rekam jejak transaksi historisnya sangat kuat. Pelanggan ini adalah tipe loyal customer yang pernah sangat terlibat dengan layanan toko, sehingga peluang reaktivasi jauh lebih besar dibanding segmen lainnya.
Ringkasan temuan utama: