Pengelompokan dan agregasi

Pola split-apply-combine untuk merangkum data per kelompok dengan groupby dan agregasi.

Daftar isi

Perangkuman per kelompok adalah operasi yang paling sering dijalankan pada data tabular, misalnya rata-rata nilai per kelas atau jumlah peminjaman per bulan. Topik ini membahas pola split-apply-combine, yakni pola membagi, menerapkan, dan menggabungkan yang melandasinya, beserta penerapannya dengan groupby dan agg pada pandas. Setelah topik ini, data mentah dapat dirangkum menjadi tabel ringkasan per kelompok yang memuat beberapa ukuran sekaligus, dilengkapi grafik pembanding antarkelompok.

Pola split-apply-combine#

Pola split-apply-combine terdiri atas tiga tahap. Tahap split membagi baris data menjadi kelompok berdasarkan nilai satu kolom, misalnya per kelas. Tahap apply menerapkan satu fungsi pada setiap kelompok secara terpisah, misalnya menghitung rata-rata. Tahap combine menggabungkan hasil setiap kelompok menjadi satu tabel ringkasan baru. Metode groupby menyatukan ketiga tahap itu dalam satu baris kode, dan diagram berikut memperlihatkan alurnya.

splitapplycombineData lengkap12 barisKelompok 7AKelompok 7BKelompok 8Arata-rata = 82.25rata-rata = 85.50rata-rata = 84.25kelasrata-rata7A82.257B85.508A84.25
Pola split-apply-combine pada perangkuman nilai matematika per kelas

Diagram tersebut menggunakan data dua belas siswa pada tiga kelas. Baris dibagi menjadi tiga kelompok pada tahap split, rata-rata matematika dihitung pada tahap apply, lalu tiga angka hasilnya digabung menjadi satu tabel kecil pada tahap combine. Pola yang sama berlaku untuk fungsi agregasi apa pun, bukan hanya rata-rata, termasuk median, jumlah, dan nilai maksimum.

Merangkum dengan groupby#

Data contoh berisi nilai dua mata pelajaran untuk dua belas siswa dari tiga kelas. Potongan pertama membangun data tersebut dari literal, menyimpannya sebagai berkas nilai-tiga-kelas.csv, lalu menampilkannya kembali. Berkas CSV itu menjadi bagian dari proyek topik ini dan tersimpan di folder topik.

python Menyiapkan data nilai tiga kelas
import pandas as pd

nilai = pd.DataFrame({
    "kelas": ["7A", "7A", "7A", "7A", "7B", "7B", "7B", "7B", "8A", "8A", "8A", "8A"],
    "nama": ["Ali", "Budi", "Citra", "Dewi", "Eka", "Fajar", "Gita", "Hadi", "Indah", "Joko", "Kartika", "Lutfi"],
    "matematika": [78, 85, 90, 76, 88, 79, 84, 91, 82, 87, 95, 73],
    "bahasa": [82, 79, 88, 81, 90, 84, 77, 86, 89, 80, 92, 78],
})
nilai.to_csv("nilai-tiga-kelas.csv", index=False)
print(pd.read_csv("nilai-tiga-kelas.csv"))
text Keluaran
   kelas     nama  matematika  bahasa
0     7A      Ali          78      82
1     7A     Budi          85      79
2     7A    Citra          90      88
3     7A     Dewi          76      81
4     7B      Eka          88      90
5     7B    Fajar          79      84
6     7B     Gita          84      77
7     7B     Hadi          91      86
8     8A    Indah          82      89
9     8A     Joko          87      80
10    8A  Kartika          95      92
11    8A    Lutfi          73      78

Panggilan nilai.groupby("kelas") mengembalikan objek bertipe DataFrameGroupBy, bukan tabel. Objek ini hanya menyimpan rencana pembagian kelompok, dan perhitungannya baru dijalankan saat fungsi agregasi dipanggil. Metode size menghitung jumlah baris per kelompok dan menjadi cara cepat memeriksa pembagiannya.

python Memeriksa objek GroupBy dan jumlah baris per kelompok
import pandas as pd

nilai = pd.read_csv("nilai-tiga-kelas.csv")

pengelompokan = nilai.groupby("kelas")
print(type(pengelompokan).__name__)
print()
print(pengelompokan.size())
text Keluaran
DataFrameGroupBy

kelas
7A    4
7B    4
8A    4
dtype: int64

Pemilihan kolom sebelum agregasi, yaitu ["matematika"] setelah groupby, membatasi perhitungan pada satu kolom. Hasil agregasinya berupa Series dengan label kelompok sebagai index.

python Menghitung rata-rata matematika per kelas
import pandas as pd

nilai = pd.read_csv("nilai-tiga-kelas.csv")

rata = nilai.groupby("kelas")["matematika"].mean()
print(rata)
text Keluaran
kelas
7A    82.25
7B    85.50
8A    84.25
Name: matematika, dtype: float64

Tiga angka pada keluaran adalah rata-rata matematika kelas 7A, 7B, dan 8A. Perhitungan yang sama tanpa groupby, yaitu nilai["matematika"].mean(), hanya menghasilkan satu rata-rata untuk seluruh siswa dan menghapus informasi per kelas. Karena itu, groupby adalah cara baku ketika pertanyaan analisis menyebut kata “per”, misalnya per kelas, per bulan, atau per kategori.

Beberapa agregasi sekaligus dengan agg#

Satu rata-rata saja jarang cukup untuk membaca kelompok. Metode agg menerima daftar nama fungsi dan menerapkannya sekaligus, sehingga hasilnya berupa tabel dengan satu kolom per fungsi agregasi.

python Menerapkan tiga fungsi agregasi sekaligus
import pandas as pd

nilai = pd.read_csv("nilai-tiga-kelas.csv")

ringkasan = nilai.groupby("kelas")["matematika"].agg(["mean", "median", "max"])
print(ringkasan)
text Keluaran
        mean  median  max
kelas                    
7A     82.25    81.5   90
7B     85.50    86.0   91
8A     84.25    84.5   95

Tabel itu menunjukkan sesuatu yang tidak terlihat pada rata-rata saja. Rata-rata ketiga kelas berdekatan, sedangkan nilai maksimumnya berjauhan. Kelas 8A memuat siswa dengan nilai tertinggi, yaitu 95, tetapi rata-ratanya justru di bawah 7B, sehingga angka maksimum saja menyesatkan sebagai ukuran kinerja kelas. Perbandingan mean dengan median yang berdekatan juga menjadi petunjuk awal bahwa sebaran nilai tiap kelompoknya tidak ekstrem.

Nama kolom mean, median, dan max berasal dari nama fungsinya, dan nama itu tidak selalu deskriptif untuk laporan. Named aggregation, yakni agregasi dengan nama kolom hasil yang ditentukan sendiri, memberi kontrol penuh atasnya. Setiap argumen menyatakan nama kolom baru beserta pasangan kolom sumber dan fungsinya.

python Agregasi bernama dengan nama kolom hasil
import pandas as pd

nilai = pd.read_csv("nilai-tiga-kelas.csv")

ringkasan = nilai.groupby("kelas").agg(
    rata_matematika=("matematika", "mean"),
    bahasa_tertinggi=("bahasa", "max"),
    jumlah_siswa=("nama", "count"),
)
print(ringkasan)
text Keluaran
       rata_matematika  bahasa_tertinggi  jumlah_siswa
kelas                                                 
7A               82.25                88             4
7B               85.50                90             4
8A               84.25                92             4

Hasilnya siap ditempatkan ke dalam laporan tanpa penggantian nama tambahan. Kolom jumlah_siswa menghitung baris terisi pada kolom nama, sehingga berfungsi sebagai penghitung anggota kelompok. Pencampuran kolom sumber dan fungsi yang berbeda dalam satu panggilan agg seperti ini adalah pola ringkasan yang lazim pada laporan analisis.

Membaca hasil agregasi dengan grafik#

Tabel ringkasan berukuran kecil sudah cukup untuk dibaca langsung. Apabila kelompoknya banyak, grafik batang membantu membandingkan ukurannya secara sekilas. Grafik berikut menggambar rata-rata matematika per kelas dari hasil groupby dan menyimpannya sebagai berkas PNG di folder topik.

python Menggambar rata-rata per kelas dan menyimpannya
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import pandas as pd

nilai = pd.read_csv("nilai-tiga-kelas.csv")
rata = nilai.groupby("kelas")["matematika"].mean()

plt.bar(rata.index, rata.values, color="#4C72B0")
plt.title("Rata-rata nilai matematika per kelas")
plt.xlabel("Kelas")
plt.ylabel("Rata-rata nilai")
plt.ylim(0, 100)
plt.savefig("rata-rata-per-kelas.png", dpi=120)
print("Gambar tersimpan sebagai rata-rata-per-kelas.png")
text Keluaran
Gambar tersimpan sebagai rata-rata-per-kelas.png

Rata-rata nilai matematika per kelas, digambar sebagai grafik batang
Rata-rata nilai matematika per kelas, digambar sebagai grafik batang

Tiga batang pada grafik memberi gambaran yang sama dengan tabel agg sebelumnya, yaitu kelas 7B sedikit di atas dua kelas lainnya dan seluruh rata-rata berada di kisaran 80 sampai 86. Grafik membuat perbandingan antarkelompok terlihat seketika, tetapi angka di baliknya tetap menjadi acuan laporan. Tabel ringkasan dan grafik yang berasal dari perhitungan yang sama menjaga keduanya tetap konsisten.

Kesalahan umum#

Kesalahan pertama adalah mengagregasi tanpa memilih kolom. Apabila groupby dipanggil tanpa pemilihan kolom, pandas mencoba menerapkan fungsi pada seluruh kolom, termasuk kolom teks seperti nama. Fungsi mean tidak berlaku untuk teks, sehingga panggilan semacam itu berakhir dengan TypeError. Pilih kolomnya secara eksplisit, misalnya ["matematika", "bahasa"], agar hanya kolom yang dimaksud yang dihitung.

Kesalahan kedua adalah melupakan bentuk index hasilnya. Hasil groupby menjadikan kolom kunci pengelompokan sebagai index, sehingga kelas tidak lagi berada di kolom. Perilaku ini praktis untuk seleksi dengan loc, tetapi menyulitkan saat hasilnya digabung dengan tabel lain. Argumen as_index=False atau metode reset_index mengembalikan kunci pengelompokan menjadi kolom biasa.

Kesalahan ketiga adalah menafsirkan rata-rata dari kelompok yang kecil tanpa kehati-hatian. Rata-rata dari empat baris mudah tergeser oleh satu nilai ekstrem, dan kelompok yang anggotanya satu atau dua baris hampir tidak memberi informasi. Periksa size sebelum menafsirkan, dan laporkan jumlah anggota kelompok bersama rata-ratanya.

Ringkasan#

  • Pola split-apply-combine bekerja dengan groupby yang membagi baris per kelompok, fungsi agregasi yang diterapkan per kelompok, dan hasil yang digabung menjadi satu tabel.
  • agg menerima beberapa fungsi sekaligus, dan named aggregation memberi nama kolom hasil yang deskriptif untuk laporan.
  • Grafik batang dari hasil groupby mempercepat perbandingan antarkelompok, sedangkan size memastikan jumlah anggota setiap kelompok sebelum penafsiran.

Referensi#