Pertanyaan analisis yang sangat sering muncul di dunia kerja berbunyi seperti ini: berapa persen kontribusi setiap transaksi terhadap total kotanya, atau berapa persen porsi setiap kategori terhadap total penjualan. Perhitungan ini menggabungkan dua teknik yang sudah kita pelajari sebelumnya, yaitu transform() untuk membawa angka agregat ke setiap baris dan pembagian element-wise untuk mengubah perbandingan menjadi persentase. Chapter ini membangun pola tersebut langkah demi langkah, lalu menutup dengan rata-rata berbobot yang memakai div() antar kolom hasil agg().
Rumus Persentase per Kelompok #
Rumusnya sederhana: persentase sebuah baris sama dengan nilai baris dibagi total kelompoknya, lalu dikalikan 100. Bagian yang menentukan kebenaran hasil bukan rumusnya, melainkan cara mendapatkan total kelompok dalam ukuran yang sejajar dengan baris. Jika kita memakai hasil groupby().sum() yang hanya berisi satu baris per kelompok, pembagian akan salah karena ukurannya tidak cocok. Di sinilah transform("sum") berperan: menghasilkan total per kelompok dengan jumlah baris dan index yang sama seperti data asli.
Langkah 1 dan 2: transform(“sum”) lalu div #
Langkah pertama adalah menghitung total_kota = df.groupby("kota")["nilai"].transform("sum"). Langkah kedua adalah membagi kolom nilai dengan total tersebut menggunakan method div(), lalu mengalikan 100 dengan mul() dan membulatkan dengan round(). Rantai method seperti .div(total).mul(100).round(1) bekerja element-wise pada posisi index yang sejajar, sehingga setiap baris dibagi dengan total kelompoknya masing-masing. Operator / juga bisa dipakai, tetapi rantai div() dan mul() membuat urutan operasi terbaca sebagai satu alur perhitungan.
Contoh Lengkap: Kontribusi Tiap Transaksi dan Tiap Kategori #
Skrip berikut menghitung dua jenis persentase. Pertama, kontribusi setiap transaksi terhadap total kotanya. Kedua, kontribusi setiap kategori terhadap total keseluruhan penjualan.
import pandas as pd
penjualan = pd.DataFrame({
"kota": ["Jakarta", "Jakarta", "Bandung", "Bandung", "Surabaya", "Surabaya", "Medan"],
"kategori": ["Elektronik", "Pakaian", "Elektronik", "Pakaian", "Elektronik", "Pakaian", "Elektronik"],
"nilai": [120, 80, 90, 70, 110, 60, 50],
})
total_kota = penjualan.groupby("kota")["nilai"].transform("sum")
penjualan["persen"] = penjualan["nilai"].div(total_kota).mul(100).round(1)
print(penjualan, "\n")
total_semua = penjualan["nilai"].sum()
kontribusi = (
penjualan.groupby("kategori")["nilai"].sum()
.div(total_semua)
.mul(100)
.round(1)
)
print("kontribusi tiap kategori terhadap total keseluruhan:")
print(kontribusi)Output yang Dihasilkan:
kota kategori nilai persen
0 Jakarta Elektronik 120 60.0
1 Jakarta Pakaian 80 40.0
2 Bandung Elektronik 90 56.2
3 Bandung Pakaian 70 43.8
4 Surabaya Elektronik 110 64.7
5 Surabaya Pakaian 60 35.3
6 Medan Elektronik 50 100.0
kontribusi tiap kategori terhadap total keseluruhan:
kategori
Elektronik 63.8
Pakaian 36.2
Name: nilai, dtype: float64Mari kita bedah perhitungannya:
- Baris 9:
transform("sum")menghasilkan total per kota pada setiap baris; Jakarta 200, Bandung 160, Surabaya 170, dan Medan 50. - Baris 10:
div(total_kota)membagi setiap nilai dengan total kotanya,mul(100)mengubah skala menjadi persen, danround(1)membulatkan ke satu desimal. Hasilnya misalnya 120 dibagi 200 dikali 100 sama dengan 60.0. - Baris 13-19: untuk perspektif kedua,
groupby("kategori")["nilai"].sum()dijumlahkan lalu dibagitotal_semuayang merupakan total seluruh penjualan, bukan total per kelompok. - Baris 21: hasilnya Elektronik 63.8 persen dan Pakaian 36.2 persen dari total keseluruhan.
Persen per Kelompok vs Persen terhadap Total Keseluruhan #
Dua perhitungan di atas memakai penyebut yang berbeda, dan pembaca laporan perlu diberi tahu mana yang sedang ditampilkan. Kolom persen pada tabel membandingkan setiap transaksi dengan total kotanya, sehingga setiap kota berjumlah 100 persen; transaksi Medan bernilai 100.0 karena hanya ada satu transaksi di kota itu. Sebaliknya, ringkasan kategori membandingkan total kategori dengan total keseluruhan, sehingga jumlah keduanya adalah 100 persen. Salah menafsirkan penyebut adalah kesalahan analisis yang paling umum pada perhitungan persentase.
Rata-rata Berbobot dengan agg() dan div() #
Pola yang sama juga berguna untuk rata-rata berbobot, yang muncul ketika kolom harga bervariasi antar transaksi. Rata-rata sederhana mean() memperlakukan setiap transaksi sama beratnya, padahal yang kita sering butuhkan adalah total nilai dibagi total kuantitas. Skrip berikut menghitungnya dengan named aggregation dari Chapter agg() dengan Beberapa Fungsi:
import pandas as pd
transaksi = pd.DataFrame({
"kota": ["Jakarta", "Jakarta", "Bandung", "Bandung"],
"qty": [10, 5, 8, 2],
"harga_satuan": [2000, 3000, 2500, 4000],
})
transaksi["nilai"] = transaksi["qty"] * transaksi["harga_satuan"]
print(transaksi, "\n")
ringkas = transaksi.groupby("kota").agg(
total_nilai=("nilai", "sum"),
total_qty=("qty", "sum"),
)
ringkas["harga_rata"] = ringkas["total_nilai"].div(ringkas["total_qty"]).round(1)
print("rata-rata harga satuan berbobot qty per kota:")
print(ringkas)Output yang Dihasilkan:
kota qty harga_satuan nilai
0 Jakarta 10 2000 20000
1 Jakarta 5 3000 15000
2 Bandung 8 2500 20000
3 Bandung 2 4000 8000
rata-rata harga satuan berbobot qty per kota:
total_nilai total_qty harga_rata
kota
Bandung 28000 10 2800.0
Jakarta 35000 15 2333.3Baris 8 menghitung nilai tiap transaksi sebagai qty * harga_satuan. Baris 11-14 merangkum per kota dengan named aggregation: total_nilai menjumlahkan nilai dan total_qty menjumlahkan kuantitas. Baris 15 membagi keduanya dengan div(), menghasilkan harga satuan rata-rata yang sebenarnya: Jakarta 2333.3, bukan 2500 dari mean() biasa, karena transaksi 2000 berbobot jauh lebih besar.
Dengan pola transform("sum") plus div(), hampir semua pertanyaan proporsi per kelompok dapat dijawab dalam dua baris kode. Referensi resmi untuk pendalaman ada pada panduan GroupBy
, DataFrameGroupBy.transform
, dan Series.div
.
Chapter berikutnya menutup Section ini dengan sebuah studi kasus utuh. Kita akan menggabungkan agg(), transform(), filter(), dan penanganan proporsi di atas untuk menjawab empat pertanyaan analisis bisnis dari satu dataset penjualan.