Chapter sebelumnya membuktikan bahwa agregasi per kelompok dapat ditulis manual dengan loop, tetapi pendekatan itu memakan tempat dan membuka peluang salah tulis. Pandas mengemas ketiga tahap split-apply-combine ke dalam satu method bernama groupby(). Pada Chapter ini kita memakai groupby() untuk satu kolom kunci, pola pengelompokan yang paling sering muncul dalam pekerjaan analisis sehari-hari. Kita juga mengenal objek GroupBy yang dihasilkannya, cara memilih kolom yang ingin diagregasi, dan perbedaan bentuk hasil antara Series dan DataFrame.

Sintaks Dasar groupby Satu Kolom #

Pola dasarnya terdiri atas tiga bagian yang selalu muncul bersama. Pertama, df.groupby("kota") meminta pandas mengelompokkan baris berdasarkan nilai kolom kota. Kedua, seleksi ["total"] memilih kolom yang akan diproses pada setiap kelompok. Ketiga, method agregasi seperti .sum() menghitung satu nilai per kelompok dan mengembalikan Series dengan kunci kelompok sebagai index. Urutan penulisannya bisa dibaca seperti kalimat: kelompokkan transaksi menurut kota, ambil kolom total-nya, lalu jumlahkan.

Mengintip Isi Objek GroupBy #

Objek GroupBy menyediakan atribut untuk memeriksa hasil pengelompokan sebelum agregasi dijalankan. Atribut ngroups menyimpan jumlah kelompok, sedangkan groups berupa dictionary yang memetakan setiap kunci kelompok ke daftar index baris anggotanya. Script berikut memeriksa objek groupby, menghitung omzet per kota, lalu membandingkan dua bentuk hasil yang berbeda.

python
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],
})

g = transaksi.groupby("kota")

print("tipe objek      :", type(g).__name__)
print("jumlah kelompok :", g.ngroups)
print("anggota kelompok:", g.groups)
print()

omzet = g["total"].sum()
print("tipe hasil omzet:", type(omzet).__name__)
print(omzet)
print()

print(g[["total"]].sum())
print()

print("ukuran tiap kelompok:")
print(g.size())

Output yang Dihasilkan:

text
tipe objek      : DataFrameGroupBy
jumlah kelompok : 3
anggota kelompok: {'Bandung': [4, 5, 6, 7], 'Jakarta': [0, 1, 2, 3], 'Surabaya': [8, 9, 10, 11]}

tipe hasil omzet: Series
kota
Bandung     359000
Jakarta     206000
Surabaya    254000
Name: total, dtype: int64

           total
kota            
Bandung   359000
Jakarta   206000
Surabaya  254000

ukuran tiap kelompok:
kota
Bandung     4
Jakarta     4
Surabaya    4
dtype: int64

Mari kita bedah baris-baris penting script di atas:

  1. Baris 20: transaksi.groupby("kota") membuat objek DataFrameGroupBy; belum ada angka yang dihitung pada baris ini.
  2. Baris 22-24: type(g).__name__ menampilkan tipe objek, g.ngroups melaporkan tiga kelompok, dan g.groups memetakan setiap kota ke index barisnya, misalnya Bandung ke [4, 5, 6, 7].
  3. Baris 27: g["total"].sum() menjalankan agregasi pada kolom total dan mengembalikan Series bernama total dengan index berupa nama kota.
  4. Baris 32: g[["total"]].sum() memakai dua kurung siku sehingga hasilnya DataFrame dengan satu kolom bernama total, bukan Series.
  5. Baris 36: g.size() menghitung banyaknya baris di setiap kelompok tanpa memandang isi kolom tertentu.

Series atau DataFrame, Kapan yang Mana? #

Tabel berikut merangkum dua bentuk seleksi yang muncul pada script tadi beserta bentuk hasilnya.

PenulisanHasil yang dikembalikanBentuk
g["total"].sum()ringkasan omzet dengan index nama kotaSeries
g[["total"]].sum()tabel satu kolom bernama totalDataFrame
g.size()banyaknya baris per kelompokSeries

Aturan praktisnya, gunakan bentuk Series ketika hasil akan langsung dibaca, diurutkan, atau dipakai dalam perhitungan berikutnya. Bentuk DataFrame lebih cocok ketika hasil akan ditambahkan agregasi kolom lain, misalnya lewat agg() yang dibahas pada chapter kelima. Keduanya berasal dari objek groupby yang sama, sehingga beralih di antara keduanya tidak memerlukan pengelompokan ulang. Konsep pengelompokan lengkapnya dirangkum pada user guide groupby , sementara parameter methodnya terdokumentasi di pandas.DataFrame.groupby dan pandas.Series.groupby .

Ukuran Kelompok dengan size() #

Method size() layak masuk daftar pertama yang dihafal karena menjawab pertanyaan paling umum: ada berapa baris pada setiap kelompok? Pada dataset transaksi, setiap kota mencatat empat transaksi sehingga ketiga angkanya sama. Nilai size() hanya menghitung baris dan tidak memandang isi kolom mana pun; perbedaan tersebut akan terasa penting ketika data mulai berisi nilai kosong.

Groupby satu kolom sudah cukup untuk banyak laporan sederhana, tetapi pertanyaan bisnis sering menuntut kombinasi dua kunci sekaligus, misalnya omzet per kota dan per kategori produk. Chapter berikutnya memperluas pola groupby ke daftar beberapa kolom dan memperkenalkan MultiIndex, struktur index bertingkat yang muncul setiap kali kita mengelompokkan data dengan lebih dari satu kunci. Pola sintaksnya nyaris sama; yang berubah hanya daftar kuncinya.