pd.cut() menempatkan batas bin pada angka yang kita pilih, dan jumlah isi tiap bin bergantung pada sebaran data. Pada data yang condong (skewed), bin lebar sama bisa berisi sangat banyak baris di satu sisi dan nyaris kosong di sisi lain. pd.qcut() bekerja dari arah sebaliknya: batas bin dihitung dari kuantil data sehingga jumlah baris tiap bin cenderung sama. Pada Chapter ini kita mempraktikkan qcut() dengan label Indonesia, membaca tepi bin lewat retbins, lalu membandingkan hasilnya dengan cut() pada dataset yang sama.

Membagi Transaksi per Kuartil #

Kuartil membagi data terurut menjadi empat bagian sama besar: 25 persen baris terendah, 25 persen berikutnya, dan seterusnya. Skrip berikut memakai q=4 sehingga setiap transaksi mendapat salah satu dari empat label tingkat belanja. Jalankan skripnya, lalu bandingkan rekap kedua method di bagian akhir output.

python
import pandas as pd

pesanan = pd.DataFrame({
    "id_pesanan": ["PSN-001", "PSN-002", "PSN-003", "PSN-004",
                   "PSN-005", "PSN-006", "PSN-007", "PSN-008"],
    "nama_pelanggan": ["Budi", "Siti", "Dewi", "Andi",
                       "Rina", "Tono", "Lina", "Sari"],
    "kota": ["Jakarta", "Bandung", "Surabaya", "Jakarta",
             "Medan", "Bandung", "Jakarta", "Surabaya"],
    "pembayaran": ["QRIS", "Transfer", "QRIS", "Kartu Kredit",
                   "COD", "Transfer", "QRIS", "COD"],
    "nilai_transaksi": [250_000, 1_800_000, 750_000, 2_400_000,
                        480_000, 1_200_000, 320_000, 980_000],
    "berat_paket": [1.2, 4.5, 0.8, 7.0, 2.5, 3.0, 1.0, 5.5],
})

nilai = pesanan["nilai_transaksi"]

pesanan["tingkat_belanja"] = pd.qcut(
    nilai, q=4, labels=["Rendah", "Menengah", "Tinggi", "Sangat Tinggi"]
)
print(pesanan[["id_pesanan", "nilai_transaksi", "tingkat_belanja"]])
print()
print(pesanan["tingkat_belanja"].value_counts())
print()

tepi = pd.qcut(nilai, q=4, retbins=True)[1]
print(tepi)
print()

kelas = pd.cut(nilai, bins=[0, 500_000, 1_500_000, 2_500_000],
               labels=["Murah", "Sedang", "Mahal"])
print(kelas.value_counts())

Output yang Dihasilkan:

text
  id_pesanan  nilai_transaksi tingkat_belanja
0    PSN-001           250000          Rendah
1    PSN-002          1800000   Sangat Tinggi
2    PSN-003           750000        Menengah
3    PSN-004          2400000   Sangat Tinggi
4    PSN-005           480000        Menengah
5    PSN-006          1200000          Tinggi
6    PSN-007           320000          Rendah
7    PSN-008           980000          Tinggi

tingkat_belanja
Rendah           2
Menengah         2
Tinggi           2
Sangat Tinggi    2
Name: count, dtype: int64

[ 250000.  440000.  865000. 1350000. 2400000.]

nilai_transaksi
Murah     3
Sedang    3
Mahal     2
Name: count, dtype: int64

Mari kita telaah apa yang terjadi pada kode di atas:

  1. Baris 17 (nilai = pesanan["nilai_transaksi"]): qcut() menerima array-like apa pun; di sini kita memisahkan kolomnya dulu agar baris 27 bisa memanggil qcut() sekali lagi dengan data yang sama.
  2. Baris 19-21 (pesanan["tingkat_belanja"] = pd.qcut(...)): argumen q=4 meminta empat bin berdasarkan kuartil, dan labels=[...] menamai kuartil pertama sampai keempat. Delapan transaksi terbagi rapi: tepat 2 baris per kelas, terlihat pada value_counts() di baris 24.
  3. Baris 27 (pd.qcut(nilai, q=4, retbins=True)[1]): argumen retbins=True membuat qcut() mengembalikan tuple berisi hasil dan tepi binnya. Tepi yang tercetak adalah 250000, 440000, 865000, 1350000, dan 2400000: kuartil pertama (440.000) adalah titik interpolasi antara 320.000 dan 480.000, bukan angka bulat pilihan manusia.
  4. Baris 31-33 (kelas = pd.cut(...)): pada data yang sama, cut() dengan tepi manual menghasilkan 3-3-2. Kontras 2-2-2-2 versus 3-3-2 inilah perbedaan inti kedua method: qcut menjaga jumlah isi, cut menjaga lebar rentang.

Kapan Memilih cut(), Kapan qcut() #

Aspekpd.cut()pd.qcut()
Batas binDitentukan manual atau dibagi rata dari rentangDihitung dari kuantil data
Isi binBergantung sebaran dataCenderung sama banyak per bin
Makna kelasRentang bisnis tetapPeringkat relatif dalam data
Contoh pakaiKelas harga Murah-Sedang-MahalKuartil belanja Rendah-Sangat Tinggi

Pilih cut() bila kelas punya makna bisnis tetap: batas 500 ribu dan 1,5 juta tetap berlaku meskipun dataset berubah. Pilih qcut() bila yang penting peringkat relatif, misalnya 25 persen transaksi termurah masuk kelas Rendah apa pun nominalnya. Karena batas qcut() dihitung dari data, angkanya berubah ketika data berubah; simpan tepi bin dari retbins bila hasil harus konsisten antar batch. Referensi detail parameter tersedia di halaman pandas.qcut() dan pandas.Series.quantile() yang menjadi dasar perhitungannya.

Hasil qcut() sama seperti cut(): kolom bertipe category yang urutan kategorinya terurut. Keduanya bisa langsung dipakai untuk peringkasan atau digabungkan dengan kolom kategori lain. Untuk kebutuhan pemodelan, kategori sering perlu diubah lagi menjadi kolom biner, dan itu topik Chapter berikutnya: one-hot encoding dengan pd.get_dummies().