Memuat Library (Packages) yang Dibutuhkan

library(dplyr)       # Untuk manipulasi data tabular (select, filter, mutate)
## 
## 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(ggplot2)     # Untuk visualisasi grafis (scatter plot)
library(tidyr)       # Untuk merapikan data
library(caret)       # Untuk proses preprocessing (seperti dummy variables)
## Warning: package 'caret' was built under R version 4.5.3
## Loading required package: lattice
# Memuat library untuk algoritma clustering
library(flexclust)   # Berisi fungsi kcca() yang akan kita gunakan untuk K-Medians
## Warning: package 'flexclust' was built under R version 4.5.3
library(cluster)     # Untuk evaluasi silhouette score

Memuat Dataset

df_kos <- read.csv("dataset_kos_final.csv", stringsAsFactors = FALSE)

str(df_kos)
## 'data.frame':    2485 obs. of  12 variables:
##  $ harga            : num  950000 1100000 1100000 700000 1500000 2200000 1350000 3100000 700000 3500000 ...
##  $ deposit          : num  0e+00 0e+00 0e+00 0e+00 5e+05 5e+05 0e+00 1e+06 0e+00 1e+06 ...
##  $ luas_m2          : num  12 12 9 12 6 9 16 12 9 15 ...
##  $ rating           : num  0 0 0 0 1 4.8 0 5 4.1 4 ...
##  $ transaksi        : num  0 0 0 0 0 0 0 0 0 22 ...
##  $ region           : chr  "Bogor" "Depok" "Tangerang Selatan" "Bogor" ...
##  $ tipe_kos         : chr  "Kos Campur" "Kos Putra" "Kos Putra" "Kos Campur" ...
##  $ listrik          : chr  "Ya" "Tidak" "Tidak" "Ya" ...
##  $ fasilitas_AC     : chr  "Tidak" "Ya" "Ya" "Tidak" ...
##  $ fasilitas_WiFi   : chr  "Tidak" "Ya" "Ya" "Tidak" ...
##  $ fasilitas_KMDalam: chr  "Ya" "Ya" "Ya" "Ya" ...
##  $ fasilitas_Parkir : chr  "Ya" "Ya" "Ya" "Ya" ...
head(df_kos)

Pra-pemrosesan Data (Data Preprocessing)

# One-Hot Encoding untuk Kolom Kategorikal
dummy_model <- dummyVars(" ~ .", data = df_kos)
df_dummy <- data.frame(predict(dummy_model, newdata = df_kos))

# Standarisasi Kolom Numerikal (Z-score scaling)
df_scaled <- df_dummy
kolom_numerik <- c("harga", "deposit", "luas_m2", "rating", "transaksi")
df_scaled[kolom_numerik] <- scale(df_scaled[kolom_numerik])
summary(df_scaled[kolom_numerik])
##      harga            deposit           luas_m2             rating       
##  Min.   :-1.5650   Min.   :-0.7838   Min.   :-0.23922   Min.   :-1.5263  
##  1st Qu.:-0.6554   1st Qu.:-0.7838   1st Qu.:-0.08387   1st Qu.:-1.5263  
##  Median :-0.1883   Median :-0.1698   Median :-0.05072   Median : 0.6027  
##  Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.00000   Mean   : 0.0000  
##  3rd Qu.: 0.4605   3rd Qu.: 0.1372   3rd Qu.:-0.02173   3rd Qu.: 0.7416  
##  Max.   :13.8254   Max.   : 9.6546   Max.   :37.01539   Max.   : 0.7879  
##    transaksi       
##  Min.   :-0.47841  
##  1st Qu.:-0.47841  
##  Median :-0.39438  
##  Mean   : 0.00000  
##  3rd Qu.: 0.02577  
##  Max.   : 9.81524

Menemukan Jumlah Cluster Optimal (Elbow Method)

k_values <- 2:10
wss_values <- numeric(length(k_values))
set.seed(123)

for (j in 1:length(k_values)) {
  k_current <- k_values[j]
  model_kmed <- kcca(df_scaled, k = k_current, family = kccaFamily("kmedians"))
  info_jarak <- info(model_kmed, "dists")
  wss_values[j] <- sum(info_jarak^2)
}

plot(k_values, wss_values,
     type = "b",
     pch = 19,
     col = "blue",
     frame = FALSE, 
     xlab = "Jumlah Cluster (K)", 
     ylab = "Total Within-Cluster Jarak Kuadrat",
     main = "Metode Elbow untuk Menentukan K Optimal",
     xaxt = "n")

axis(1, at = k_values)
abline(v = 3, col = "red", lty = 2, lwd = 2)

Menjalankan Algoritma K-Medians

set.seed(123)

k_optimal <- 3
kmed_final <- kcca(df_scaled, k = k_optimal, family = kccaFamily("kmedians"))
label_cluster <- clusters(kmed_final)
df_kos$Cluster <- as.factor(label_cluster)
cat("Jumlah data pada masing-masing Cluster:\n")
## Jumlah data pada masing-masing Cluster:
table(df_kos$Cluster)
## 
##    1    2    3 
##  967  277 1241

Reduksi Dimensi dengan PCA (Visualisasi 2D)

pca_result <- prcomp(df_scaled, center = TRUE, scale. = FALSE)

df_pca <- data.frame(
  PC1 = pca_result$x[, 1],
  PC2 = pca_result$x[, 2]
)

df_pca$Cluster <- as.factor(label_cluster)

ggplot(df_pca, aes(x = PC1, y = PC2, color = Cluster)) +
  geom_point(alpha = 0.6, size = 2) + # alpha untuk transparansi titik
  stat_ellipse(level = 0.95, linetype = 2) + # Menambahkan lingkaran (elips) batas cluster
  theme_minimal() +
  labs(
    title = "Visualisasi Hasil Clustering K-Medians (Dimensi PCA)",
    subtitle = paste("K =", k_optimal),
    x = "Principal Component 1 (PC1)",
    y = "Principal Component 2 (PC2)",
    color = "Kelompok (Cluster)"
  ) +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"),
        plot.subtitle = element_text(hjust = 0.5))

Interpretasi dan Profiling Cluster (Cluster Profiling)

get_mode <- function(v) {
  uniqv <- unique(v)
  uniqv[which.max(tabulate(match(v, uniqv)))]
}

profil_numerik <- df_kos %>%
  group_by(Cluster) %>%
  summarise(
    Jumlah_Kos = n(),
    Median_Harga = median(harga, na.rm = TRUE),
    Median_Deposit = median(deposit, na.rm = TRUE),
    Median_Luas = median(luas_m2, na.rm = TRUE),
    Median_Rating = median(rating, na.rm = TRUE),
    Median_Transaksi = median(transaksi, na.rm = TRUE)
  )

cat("--- Profil Numerik Tiap Cluster (Lengkap) ---\n")
## --- Profil Numerik Tiap Cluster (Lengkap) ---
print(profil_numerik)
## # A tibble: 3 × 7
##   Cluster Jumlah_Kos Median_Harga Median_Deposit Median_Luas Median_Rating
##   <fct>        <int>        <dbl>          <dbl>       <dbl>         <dbl>
## 1 1              967      1300000         150000        9.25           4.6
## 2 2              277      2545000        1000000       12              4.6
## 3 3             1241      1500000         200000       11              4.6
## # ℹ 1 more variable: Median_Transaksi <dbl>
profil_kategori <- df_kos %>%
  group_by(Cluster) %>%
  summarise(
    Modus_Tipe_Kos = get_mode(tipe_kos),
    Modus_Region = get_mode(region),
    Modus_Listrik = get_mode(listrik),
    Modus_AC = get_mode(fasilitas_AC),
    Modus_WiFi = get_mode(fasilitas_WiFi),
    Modus_KMDalam = get_mode(fasilitas_KMDalam),
    Modus_Parkir = get_mode(fasilitas_Parkir)
  )

cat("\n--- Profil Kategori/Fasilitas Tiap Cluster (Lengkap) ---\n")
## 
## --- Profil Kategori/Fasilitas Tiap Cluster (Lengkap) ---
print(profil_kategori)
## # A tibble: 3 × 8
##   Cluster Modus_Tipe_Kos Modus_Region  Modus_Listrik Modus_AC Modus_WiFi
##   <fct>   <chr>          <chr>         <chr>         <chr>    <chr>     
## 1 1       Kos Putri      Depok         Tidak         Ya       Ya        
## 2 2       Kos Campur     Jakarta Barat Tidak         Ya       Ya        
## 3 3       Kos Campur     Bekasi        Tidak         Ya       Ya        
## # ℹ 2 more variables: Modus_KMDalam <chr>, Modus_Parkir <chr>

Kesimpulan Bisnis & Profiling Segmen Kos (Persona)

Berdasarkan hasil pemodelan clustering K-Medians, pasar properti kos di dataset ini terbagi menjadi tiga segmen utama dengan karakteristik spesifik:

1. Cluster 1: “Segmen Mahasiswi Praktis & Ekonomis” (Fokus Wilayah Depok)

  • Fakta Data: Ini adalah segmen dengan harga sewa paling murah (Rp 1.300.000) dan luas kamar paling mungil (9.25 m2). Uang depositnya pun sangat ringan (Rp 150.000). Secara kategorikal, kos di segmen ini didominasi oleh tipe Kos Putri dan berlokasi di Depok.

  • Interpretasi & Persona: Mengingat Depok adalah salah satu pusat pendidikan (kampus besar seperti UI dan Gunadarma), kos dengan spesifikasi ini sangat menyasar mahasiswi yang mencari kepraktisan. Kamar tidak perlu terlalu luas, yang penting harganya terjangkau, aman (khusus putri), dan fasilitas dasarnya sudah modern (AC & WiFi).

  • Strategi Bisnis / Rekomendasi: Untuk kos tipe ini, promosi paling efektif dilakukan menjelang tahun ajaran baru perguruan tinggi. Karena depositnya murah, ini adalah daya tarik besar bagi kantong mahasiswa.

2. Cluster 3: “Segmen Menengah Populer / Fast-Moving” (Fokus Wilayah Bekasi)

  • Fakta Data: Ini adalah populasi terbesar di dataset (1.241 kos). Harganya berada di titik tengah (Rp 1.500.000) dengan ukuran kamar yang sangat pas (11 m2) dan deposit wajar (Rp 200.000). Yang paling menarik, tingkat transaksinya adalah yang tertinggi (3). Tipe kos didominasi Kos Campur di wilayah Bekasi.

  • Interpretasi & Persona: Ini adalah kos tipe “Sweet Spot” alias yang paling dicari pasar. Penghuninya kemungkinan besar adalah pekerja kerah putih muda (first-jobber) kaum komuter yang bekerja di Jakarta tapi indekos di daerah satelit seperti Bekasi untuk menekan biaya hidup, namun tetap menginginkan privasi dan kenyamanan ruang yang pas.

  • Strategi Bisnis / Rekomendasi: Kos di segmen ini adalah pendorong pendapatan utama (cash cow) karena tingkat transaksinya tinggi (cepat penuh / laku). Pemilik kos atau platform bisa memberikan fitur booking cepat atau layanan ekstra (seperti layanan pembersihan) karena segmen pekerja biasanya rela membayar sedikit lebih mahal untuk kenyamanan.

3. Cluster 2: “Segmen Eksklusif Premium” (Fokus Wilayah Jakarta Barat)

  • Fakta Data: Segmen dengan populasi terkecil (hanya 277 kos) namun memiliki harga yang sangat premium (Rp 2.545.000) dan deposit sangat tinggi (Rp 1.000.000). Sesuai dengan harganya, ukuran kamarnya paling lega (12 m2). Segmen ini didominasi Kos Campur di pusat kota, yaitu Jakarta Barat.

  • Interpretasi & Persona: Segmen ini menyasar para eksekutif muda, pekerja profesional, atau mahasiswa mapan yang sangat mementingkan status, kenyamanan, dan lokasi strategis di tengah kota Jakarta. Uang deposit yang mencapai 1 juta rupiah berfungsi sebagai filter sosial, memastikan bahwa penghuninya berasal dari kalangan menengah ke atas yang komit.

  • Strategi Bisnis / Rekomendasi: Tidak perlu repot mempromosikan kos ini dengan embel-embel “diskon”. Promosi harus menonjolkan kesan eksklusif, tingkat privasi, keamanan berlapis, dan kedekatan dengan sentra bisnis atau pusat perbelanjaan di Jakarta Barat.