Pertanyaan analisis di dunia kerja jarang berhenti pada satu angka keseluruhan. Manajer toko lebih tertarik pada omzet per kota, transaksi per kategori, atau rata-rata nilai belanja per wilayah daripada satu total besar. Menjawabnya secara manual berarti menyalin data berulang-ulang dan membuka peluang salah hitung. Groupby pada pandas dirancang khusus untuk pola pekerjaan ini, dan polanya memiliki nama resmi: split-apply-combine. Pada Chapter ini kita membedah ketiga tahap tersebut secara manual agar mekanismenya terlihat jelas, sebelum dipangkas menjadi satu method pada chapter berikutnya.
Dataset Transaksi untuk Sepanjang Section #
Seluruh chapter pada Section ini memakai satu dataset yang sama: catatan 12 transaksi sebuah toko sembako yang memiliki cabang di tiga kota. Setiap baris merekam satu penjualan dengan enam kolom yang tercantum pada tabel berikut. Dataset ini sengaja dibuat kecil agar kita bisa memverifikasi setiap angka output dengan hitungan tangan. Kebiasaan menghitung ulang hasil agregasi seperti ini tetap berguna ketika data sungguhan berisi ratusan ribu baris.
| Kolom | Isi | Contoh nilai |
|---|---|---|
kota | cabang toko tempat transaksi terjadi | Jakarta, Bandung, Surabaya |
kategori | jenis barang yang dijual | Minuman, Makanan, Sembako |
produk | nama barang yang terjual | Kopi Gayo, Beras Premium |
jumlah | banyak unit yang terjual | 3, 10 |
harga | harga satuan dalam rupiah | 18000, 3500 |
total | nilai transaksi (jumlah dikali harga) | 54000, 204000 |
Tiga Tahap Split, Apply, dan Combine #
Istilah split-apply-combine dipopulerkan oleh statistikawan Hadley Wickham dalam papernya tahun 2011 tentang strategi analisis data. Strategi ini membagi pekerjaan agregasi menjadi tiga langkah yang berurutan. Tahap split memecah DataFrame menjadi beberapa kelompok berdasarkan nilai sebuah kolom kunci, misalnya semua baris dengan kota bernilai Bandung. Tahap apply menerapkan satu fungsi pada setiap kelompok secara terpisah, misalnya sum() untuk menjumlahkan kolom total. Tahap combine menggabungkan hasil per kelompok menjadi satu objek baru, biasanya Series atau DataFrame dengan satu baris per kelompok.
Diagram di atas memperlihatkan alur data pada dataset transaksi kita. Satu DataFrame berisi 12 baris masuk ke tahap split dan keluar sebagai tiga kelompok kecil, setiap kelompok diproses fungsi sum() pada tahap apply, lalu hasilnya disatukan kembali menjadi satu Series berisi tiga angka pada tahap combine. Pengurangan detail seperti ini memang inti dari agregasi: kita menukar isi baris demi baris dengan ringkasan yang bisa dijadikan dasar keputusan. Pola yang sama dirangkum resmi oleh pandas pada halaman Group by: split-apply-combine
.
Membedah Ketiga Tahap dengan Kode #
Agar ketiga tahap tidak berhenti sebagai teori, script berikut mengimplementasikannya secara manual dengan loop Python biasa. Script mencetak ukuran setiap kelompok, hasil sum() per kelompok, lalu menggabungkannya menjadi Series. Di bagian akhir, groupby() dipanggil dalam satu baris untuk membuktikan hasilnya identik.
import pandas as pd
transaksi = pd.DataFrame({
"kota": ["Jakarta", "Jakarta", "Jakarta", "Jakarta",
"Bandung", "Bandung", "Bandung", "Bandung",
"Surabaya", "Surabaya", "Surabaya", "Surabaya"],
"kategori": ["Minuman", "Minuman", "Makanan", "Sembako",
"Minuman", "Makanan", "Sembako", "Makanan",
"Minuman", "Sembako", "Makanan", "Minuman"],
"produk": ["Kopi Gayo", "Teh Melati", "Roti Tawar", "Beras Premium",
"Kopi Gayo", "Roti Tawar", "Beras Premium", "Mie Instan",
"Teh Melati", "Beras Premium", "Mie Instan", "Kopi Gayo"],
"jumlah": [3, 2, 4, 1, 5, 2, 3, 10, 6, 2, 8, 1],
"harga": [18000, 12000, 15000, 68000, 18000, 15000, 68000, 3500,
12000, 68000, 3500, 18000],
"total": [54000, 24000, 60000, 68000, 90000, 30000, 204000, 35000,
72000, 136000, 28000, 18000],
})
print("Dataset transaksi:")
print(transaksi)
print()
print("== Tahap 1: SPLIT ==")
kelompok = {}
for kota in sorted(transaksi["kota"].unique()):
kelompok[kota] = transaksi[transaksi["kota"] == kota]
print(f"{kota}: {len(kelompok[kota])} baris")
print()
print("== Tahap 2: APPLY ==")
hasil = {}
for kota, baris in kelompok.items():
hasil[kota] = baris["total"].sum()
print(f"sum(total) kota {kota} = {hasil[kota]}")
print()
print("== Tahap 3: COMBINE ==")
ringkasan = pd.Series(hasil, name="total")
ringkasan.index.name = "kota"
print(ringkasan)
print()
print("Satu baris groupby memberi hasil yang sama:")
print(transaksi.groupby("kota")["total"].sum())Output yang Dihasilkan:
Dataset transaksi:
kota kategori produk jumlah harga total
0 Jakarta Minuman Kopi Gayo 3 18000 54000
1 Jakarta Minuman Teh Melati 2 12000 24000
2 Jakarta Makanan Roti Tawar 4 15000 60000
3 Jakarta Sembako Beras Premium 1 68000 68000
4 Bandung Minuman Kopi Gayo 5 18000 90000
5 Bandung Makanan Roti Tawar 2 15000 30000
6 Bandung Sembako Beras Premium 3 68000 204000
7 Bandung Makanan Mie Instan 10 3500 35000
8 Surabaya Minuman Teh Melati 6 12000 72000
9 Surabaya Sembako Beras Premium 2 68000 136000
10 Surabaya Makanan Mie Instan 8 3500 28000
11 Surabaya Minuman Kopi Gayo 1 18000 18000
== Tahap 1: SPLIT ==
Bandung: 4 baris
Jakarta: 4 baris
Surabaya: 4 baris
== Tahap 2: APPLY ==
sum(total) kota Bandung = 359000
sum(total) kota Jakarta = 206000
sum(total) kota Surabaya = 254000
== Tahap 3: COMBINE ==
kota
Bandung 359000
Jakarta 206000
Surabaya 254000
Name: total, dtype: int64
Satu baris groupby memberi hasil yang sama:
kota
Bandung 359000
Jakarta 206000
Surabaya 254000
Name: total, dtype: int64Mari kita bedah baris-baris penting script di atas:
- Baris 20-21:
print(transaksi)menampilkan dataset lengkap; 12 baris inilah bahan baku seluruh proses. - Baris 24-28 (tahap split):
sorted(transaksi["kota"].unique())mengambil daftar kota unik, dan filter Booleantransaksi["kota"] == kotamemecah dataset menjadi tiga sub-DataFrame yang disimpan di dictionarykelompok. - Baris 31-35 (tahap apply): loop kedua memanggil
baris["total"].sum()pada setiap sub-DataFrame;sum()adalah fungsi agregasi karena mengembalikan satu angka untuk satu kelompok. - Baris 38-41 (tahap combine): dictionary
hasildiubah menjadi Series lewatpd.Series(hasil, name="total"), danringkasan.index.name = "kota"menamai indexnya. - Baris 44-45:
transaksi.groupby("kota")["total"].sum()menghasilkan Series yang nilai dan urutannya sama persis dengan hasil manual kita.
Urutan Kelompok dan Parameter sort #
Loop manual pada script sengaja memakai sorted(), dan alasannya bukan sekadar gaya penulisan. Method unique() mengembalikan nilai sesuai urutan kemunculan pertama (Jakarta, Bandung, Surabaya), sedangkan groupby() mengurutkan kunci kelompok secara alfabetis karena parameter sort bernilai True secara default. Tanpa sorted(), dua output pada script tadi akan berisi nilai yang sama tetapi urutan barisnya berbeda. Bila urutan kemunculan lebih penting, panggil groupby dengan sort=False sehingga hasilnya mengikuti urutan data asli.
Sekarang kita tahu bahwa groupby hanyalah otomatisasi dari tiga tahap yang bisa kita tulis manual; tanda tangan lengkap method ini terdokumentasi pada pandas.DataFrame.groupby
. Chapter berikutnya memakai groupby() langsung pada satu kolom kunci, dari membuat objeknya sampai memilih bentuk hasil. Setelah pola satu kolom dikuasai, kita perluas ke pengelompokan dua kolom sekaligus.