Data bersih 30 baris kini berdiri di atas fondasi yang teruji, dan saatnya mendengarkan cerita di dalamnya. Eksplorasi pada bagian ini punya tiga sasaran: merangkum kedua kolom angka dengan statistik deskriptif, memetakan sebaran kunjungan dan belanja pelanggan, dan mengintip apakah data ini memang menyimpan struktur kelompok seperti yang kita harapkan sejak Bagian 1. Hasil eksplorasi bukan sekadar hiburan — ia akan menentukan fitur apa yang layak dibuat pada Bagian 5 dan memberi dugaan yang bisa dibandingkan dengan hasil clustering nanti.
Statistik Deskriptif Dua Kolom Utama #
Dua kolom angka yang tersedia adalah kunjungan_30hari dan belanja_ribu. Kita ringkas keduanya dengan describe() menggunakan resep bersih dari Bagian 3:
import pandas as pd
def muat_bersih(path):
"""Muat data mentah pelanggan dan terapkan seluruh langkah pembersihan."""
df = pd.read_csv(path)
df = df.drop_duplicates().reset_index(drop=True)
df["kunjungan_30hari"] = pd.to_numeric(df["kunjungan_30hari"], errors="coerce")
df = df.dropna(subset=["kunjungan_30hari"]).reset_index(drop=True)
df["kota"] = df["kota"].str.strip().str.title()
df["kunjungan_30hari"] = df["kunjungan_30hari"].astype(int)
return df
bersih = muat_bersih("../data/pelanggan.csv")
angka = bersih[["kunjungan_30hari", "belanja_ribu"]]
print(angka.describe().round(2).to_string())Output yang Dihasilkan:
kunjungan_30hari belanja_ribu
count 30.00 30.00
mean 12.57 464.67
std 7.05 70.79
min 3.00 330.00
25% 6.50 423.00
50% 11.00 450.00
75% 19.75 491.50
max 25.00 700.00Mari kita baca angka-angka kuncinya — teknik membacanya sendiri sudah kita bahas pada chapter Analisis Data Numerik :
- Kunjungan menyebar lebar: rata-rata 12,57 dengan simpangan baku 7,05 — dari yang datang 3 kali sampai 25 kali per 30 hari. Pelanggan member memang bukan kelompok seragam.
- Total belanja justru menyebar sempit: rata-rata 464,67 dengan simpangan baku hanya 70,79; 75% pelanggan berbelanja di bawah 491,5. Hampir semua member mengeluarkan Rp 330-700 ribu per bulan.
- Kombinasi keduanya mencurigakan dengan cara yang menarik: frekuensi kunjungan berlipat hampir delapan kali, tetapi total belanja nyaris datar. Pola seperti ini hampir pasti berarti cara belanja per kunjungan berbeda drastis antar pelanggan.
Sebaran Kunjungan: Tiga Gerombolan Alami #
Untuk melihat bentuk sebaran kunjungan, kita kelompokkan pelanggan ke dalam tiga rentang dan hitung jumlah serta rata-rata belanja tiap kelompok:
import pandas as pd
def muat_bersih(path):
"""Muat data mentah pelanggan dan terapkan seluruh langkah pembersihan."""
df = pd.read_csv(path)
df = df.drop_duplicates().reset_index(drop=True)
df["kunjungan_30hari"] = pd.to_numeric(df["kunjungan_30hari"], errors="coerce")
df = df.dropna(subset=["kunjungan_30hari"]).reset_index(drop=True)
df["kota"] = df["kota"].str.strip().str.title()
df["kunjungan_30hari"] = df["kunjungan_30hari"].astype(int)
return df
bersih = muat_bersih("../data/pelanggan.csv")
kelompok = pd.cut(
bersih["kunjungan_30hari"],
bins=[2, 7, 15, 30],
labels=["rendah (3-6)", "menengah (8-14)", "tinggi (18-25)"],
)
ringkas = bersih.groupby(kelompok, observed=False).agg(
jumlah=("pelanggan", "count"),
kunjungan_min=("kunjungan_30hari", "min"),
kunjungan_maks=("kunjungan_30hari", "max"),
rata_belanja=("belanja_ribu", "mean"),
)
print(ringkas.round(2).to_string())
yang_ada = set(bersih["kunjungan_30hari"])
hilang = sorted(set(range(3, 26)) - yang_ada)
print("\nJumlah kunjungan yang tidak dimiliki siapa pun antara 3-25:", hilang)Output yang Dihasilkan:
jumlah kunjungan_min kunjungan_maks rata_belanja
kunjungan_30hari
rendah (3-6) 8 3 6 502.50
menengah (8-14) 12 8 14 448.25
tinggi (18-25) 10 18 25 454.10
Jumlah kunjungan yang tidak dimiliki siapa pun antara 3-25: [7, 15, 16, 17]Dua pengamatan penting muncul dari tabel tersebut:
- Kunjungan membentuk tiga gerombolan yang dipisahkan zona kosong. Tidak ada satu pun pelanggan dengan 7 kunjungan, begitu pula 15-17: kelompok rendah berhenti di 6, kelompok menengah bergerak di 8-14, dan kelompok tinggi mulai dari 18. Zona kosong ini tanda struktur yang nyata, bukan sekadar hasil pengaturan bins yang kita pilih.
- Rata-rata total belanja ketiga kelompok nyaris sama — 502,50; 448,25; 454,10. Kelompok yang datang 18-25 kali menghasilkan total belanja yang hampir sama dengan kelompok yang datang 3-6 kali. Ini memperkuat curiga Bagian 1: total belanja tidak membedakan pelanggan, dan pembeda aslinya ada di tempat lain.
Mencari Struktur lewat Scatter Plot #
Angka-angka tadi mengajak kita menggambar. Kita buat dua panel: kiri memetakan kunjungan terhadap total belanja, kanan memetakan kunjungan terhadap hasil bagi total belanja dengan jumlah kunjungan — coba-coba sederhana yang terinspirasi dari pengamatan bahwa total belanja datar:
import matplotlib.pyplot as plt
import pandas as pd
def muat_bersih(path):
"""Muat data mentah pelanggan dan terapkan seluruh langkah pembersihan."""
df = pd.read_csv(path)
df = df.drop_duplicates().reset_index(drop=True)
df["kunjungan_30hari"] = pd.to_numeric(df["kunjungan_30hari"], errors="coerce")
df = df.dropna(subset=["kunjungan_30hari"]).reset_index(drop=True)
df["kota"] = df["kota"].str.strip().str.title()
df["kunjungan_30hari"] = df["kunjungan_30hari"].astype(int)
return df
bersih = muat_bersih("../data/pelanggan.csv")
rasio = bersih["belanja_ribu"] / bersih["kunjungan_30hari"]
fig, (ax_kiri, ax_kanan) = plt.subplots(1, 2, figsize=(11, 4.5), sharex=True)
ax_kiri.scatter(bersih["kunjungan_30hari"], bersih["belanja_ribu"],
color="#6f4e37", alpha=0.75)
ax_kiri.set_title("Total belanja: awan titik yang datar")
ax_kiri.set_xlabel("Kunjungan 30 hari")
ax_kiri.set_ylabel("Total belanja (ribu rupiah)")
ax_kanan.scatter(bersih["kunjungan_30hari"], rasio, color="#2a6f4e", alpha=0.75)
ax_kanan.set_title("Belanja per kunjungan: tiga gerombolan")
ax_kanan.set_xlabel("Kunjungan 30 hari")
ax_kanan.set_ylabel("Belanja per kunjungan (ribu rupiah)")
fig.tight_layout()
plt.show()Kedua panel menceritakan dua dunia yang berbeda. Panel kiri berupa awan cokelat yang memanjang datar: titik-titik berbaris di kisaran 330-700 pada seluruh rentang kunjungan, tanpa gerombolan yang bisa dipisahkan mata — total belanja memang tidak menyimpan struktur. Panel kanan berubah total begitu sumbu tegaknya diganti hasil bagi belanja per kunjungan: tiga gerombolan hijau terpisah jelas. Satu gerombolan mengumpul di kiri atas (jarang datang, 80-150 ribu per kunjungan), satu di tengah (8-14 kali, 32-58 ribu), dan satu lagi melebar di kanan bawah (18-25 kali, 18-25 ribu). Katalog pola seperti ini bisa dilatih pada Matplotlib Plot Types .
Struktur tiga kelompok kini terlihat oleh mata, tetapi mata manusia belum bisa dipertanggungjawabkan pada laporan. Kita perlu fitur yang terdefinisi tegas dan algoritme yang menemukan kelompok dengan aturan yang bisa diulang — dimulai dari membenahi fiturnya pada Bagian 5: Membuat Fitur .