Pertanyaan analisis yang sangat umum berbunyi: dari seluruh pembelian, berapa kali pelanggan Bandung membayar lewat QRIS, Kartu, atau Transfer? Jawabannya adalah tabel frekuensi silang (cross tabulation): baris untuk satu kategori, kolom untuk kategori kedua, dan isi sel berupa jumlah kejadian. pd.crosstab() adalah jalan pintas pandas untuk tabel ini; di balik layar fungsi tersebut menjalankan kombinasi groupby dan pivot_table yang sudah kita pelajari. Pada Chapter ini kita menghitung frekuensi pembayaran per kota, mengubah hitungan menjadi proporsi, menambahkan total, dan mengagregasi kolom lain di dalam sel.
Menghitung Frekuensi Kombinasi Kategori #
Argumen pertama pd.crosstab() menjadi baris dan argumen kedua menjadi kolom; keduanya biasanya kolom kategori yang diambil dari tabel yang sama. File berikut menghitung distribusi metode pembayaran pada tiga kota, kemudian menyempurnakannya dalam tiga bentuk laporan.
import pandas as pd
pembelian = pd.DataFrame({
"kota": ["Bandung", "Bandung", "Bandung", "Jakarta", "Jakarta",
"Jakarta", "Surabaya", "Surabaya"],
"pembayaran": ["QRIS", "QRIS", "Kartu", "QRIS", "Kartu",
"Transfer", "QRIS", "Transfer"],
})
# Tabel frekuensi silang: hitung kemunculan tiap kombinasi
tab = pd.crosstab(pembelian["kota"], pembelian["pembayaran"])
print(tab)
print()
# normalize="index": proporsi per baris
proporsi = pd.crosstab(pembelian["kota"], pembelian["pembayaran"],
normalize="index")
print(proporsi)
print()
# margins: total baris dan kolom
ringkas = pd.crosstab(pembelian["kota"], pembelian["pembayaran"],
margins=True, margins_name="Total")
print(ringkas)
print()
# values + aggfunc: agregasi kolom lain, bukan sekadar hitung baris
pesanan = pd.DataFrame({
"kota": ["Bandung", "Bandung", "Jakarta", "Jakarta", "Surabaya"],
"pembayaran": ["QRIS", "Kartu", "QRIS", "QRIS", "Transfer"],
"nominal": [250000, 180000, 120000, 90000, 150000],
})
print(pd.crosstab(pesanan["kota"], pesanan["pembayaran"],
values=pesanan["nominal"], aggfunc="sum"))Output yang Dihasilkan:
pembayaran Kartu QRIS Transfer
kota
Bandung 1 2 0
Jakarta 1 1 1
Surabaya 0 1 1
pembayaran Kartu QRIS Transfer
kota
Bandung 0.333333 0.666667 0.000000
Jakarta 0.333333 0.333333 0.333333
Surabaya 0.000000 0.500000 0.500000
pembayaran Kartu QRIS Transfer Total
kota
Bandung 1 2 0 3
Jakarta 1 1 1 3
Surabaya 0 1 1 2
Total 2 4 2 8
pembayaran Kartu QRIS Transfer
kota
Bandung 180000.0 250000.0 NaN
Jakarta NaN 210000.0 NaN
Surabaya NaN NaN 150000.0Mari kita telaah bagian-bagian pentingnya:
- Baris 10-12 (
crosstabdasar): delapan baris pembelian diringkas menjadi tabel 3x3; sel Bandung-QRIS bernilai 2 karena kombinasi itu muncul dua kali, dan kombinasi yang tidak muncul (misalnya Surabaya-Kartu) bernilai 0, bukan kosong. - Label axis: index menerima nama
kotadan kolom menerima namapembayarandari kolom sumbernya, sehingga tabel hasil langsung terbaca tanpa pengaturan tambahan. - Baris 15-19 (
normalize): nilai"index"membagi setiap sel dengan total barisnya; Bandung menunjukkan 0.666667 untuk QRIS karena dua dari tiga pembeliannya memakai QRIS. Opsi lainnya adalah"columns"(proporsi per kolom) dan"all"(proporsi terhadap seluruh tabel). - Baris 21-24 (
margins): baris dan kolomTotalmenambahkan penjumlahan tiap arah; sel 8 di sudut adalah jumlah seluruh pembelian. - Baris 27-34 (
values+aggfunc): dengan keduanya, isi sel berubah dari hitungan baris menjadi hasil agregasi kolomnominal; kombinasi tanpa data menjadiNaN, misalnya Jakarta-Kartu.
Frekuensi, Proporsi, dan Total #
Tabel frekuensi mentah sering menyesatkan ketika jumlah barisnya tidak setara; tiga pembelian Bandung dibandingkan dua pembelian Surabaya membuat angka absolut sulit dinilai. normalize="index" menyelesaikannya dengan mengubah isi sel menjadi proporsi per baris, dan hasilnya bertipe float64. Parameter margins=True memasangkan hitungan dengan total, dan margins_name mengganti label default "All" menjadi "Total". Ketika satu variabel memiliki lebih dari dua dimensi, berikan list pada argumen pertama, misalnya [pembelian["kota"], pembelian["tipe"]], dan pandas akan membentuk MultiIndex baris.
Hubungan crosstab dengan pivot_table #
pd.crosstab(index, columns) menghasilkan tabel yang sama persis dengan pivot_table(aggfunc="size", fill_value=0) atas data yang sama; perbedaannya terletak pada kepraktisan. Crosstab mengisi sel kosong dengan 0 secara default, menerima values dan aggfunc untuk agregasi lain, dan dirancang khusus untuk dua kolom kategori. Tetap beri perhatian pada satu perbedaan hasil: pada mode values + aggfunc, kombinasi tanpa data menjadi NaN dan perlu .fillna(0) bila sel kosong harus bernilai nol. Jika analisis membutuhkan lebih dari dua dimensi sekaligus dengan kontrol penuh, pivot_table tetap menjadi alat yang lebih fleksibel.
Dokumentasi user guide reshaping
memuat crosstab dalam keluarga pembentuk tabel, dan referensi pandas.crosstab
merinci semua parameter termasuk normalize dan margins. Dengan crosstab, seluruh alat pada Section Menggabungkan dan Membentuk Data telah lengkap: kita dapat merangkai tabel dari banyak sumber, memasangkan baris lewat kunci dan waktu, lalu membentuk ulang hasilnya sesuai kebutuhan. Chapter berikutnya membuka Section baru, Data Waktu dan Deret Waktu, dengan mengolah kolom waktu yang sudah beberapa kali kita singgung.