pivot dan pivot_table

Mengubah data panjang ke lebar dengan pivot dan pivot_table beserta agregasinya.

Daftar isi

Fungsi pivot mengubah tabel panjang menjadi tabel lebar dengan menuntut setiap pasangan baris dan kolom muncul paling banyak satu kali. Topik ini membahas pemakaian pivot pada kunci yang unik, error ValueError ketika pasangan kunci duplikat, serta pemakaian pivot_table yang mengatasi duplikat melalui agregasi beserta parameter fill_value dan margins. Seluruh contoh dijalankan pada data mini log sensor dan pada dataset kontrak 96 baris.

pivot memutar nilai kolom menjadi nama kolom#

Fungsi pivot menempatkan nilai unik sebuah kolom sebagai nama kolom baru, sehingga tabel melebar tanpa mengubah satu pun nilai. Tiga argumen menentukan hasilnya, yaitu index yang menjadi indeks baris, columns yang nilai uniknya menjadi nama kolom, dan values yang mengisi sel. Jalankan potongan berikut pada data mini enam baris, lalu simpan datanya untuk potongan-potongan berikutnya.

python pivot pada data mini dengan kunci unik
import pandas as pd

panjang = pd.DataFrame({
    "waktu": ["08:00", "08:00", "08:00", "08:15", "08:15", "08:15"],
    "ruang": ["Lab A", "Lab B", "Ruang Arsip", "Lab A", "Lab B", "Ruang Arsip"],
    "suhu_c": [23.5, 22.8, 21.0, 23.9, 22.6, 20.9],
})
panjang.to_csv("mini_log.csv", index=False)  # disimpan agar blok berikutnya cukup membaca berkas ini
lebar = panjang.pivot(index="waktu", columns="ruang", values="suhu_c")
print(lebar)
text Keluaran
ruang  Lab A  Lab B  Ruang Arsip
waktu
08:00   23.5   22.8         21.0
08:15   23.9   22.6         20.9

Setiap pasangan waktu dan ruang pada data mini muncul tepat satu kali, sehingga setiap sel hasil punya tepat satu kandidat nilai dan operasi selesai tanpa keputusan tambahan. Syarat kunci unik itulah yang menjadi kontrak pivot. Pada data log yang lebih besar, syarat ini mudah dilanggar tanpa disadari, dan pelanggarannya selalu tampak sebagai error, bukan sebagai hasil yang salah.

ValueError ketika pasangan kunci duplikat#

pivot melempar ValueError ketika pasangan (index, columns) muncul lebih dari satu kali, karena dua kandidat nilai untuk satu sel tidak dapat ditempatkan sekaligus. Dataset kontrak 96 baris memiliki waktu yang semuanya unik, tetapi pasangan lain tetap bisa duplikat apabila kolom yang tepat dipilih. Bangun datasetnya, lalu hitung duplikatnya.

python Membangun dataset log sensor 96 baris
import numpy as np
import pandas as pd

rng = np.random.default_rng(42)
n = 96
df = pd.DataFrame({
    "waktu": pd.date_range("2026-01-05 07:00", periods=n, freq="15min"),
    "ruang": rng.choice(["Lab A", "Lab B", "Ruang Arsip"], n, p=[0.4, 0.35, 0.25]),
    "suhu_c": np.round(rng.normal(24, 1.5, n), 1),
    "lembap_pct": np.round(rng.normal(60, 5, n), 1),
    "status_sensor": rng.choice(["normal", "kalibrasi", "rusak"], n, p=[0.85, 0.10, 0.05]),
})
df.to_csv("sensor_log.csv", index=False)  # disimpan agar blok berikutnya cukup membaca berkas ini
print("pasangan (ruang, status_sensor) duplikat:", df.duplicated(subset=["ruang", "status_sensor"]).sum())
text Keluaran
pasangan (ruang, status_sensor) duplikat: 88

pivot dengan index="ruang" dan columns="status_sensor" langsung menabrak 88 pasangan duplikat itu. Baca kembali berkasnya, lalu jalankan demo penanganan error berikut dan amati pesan aslinya.

python pivot melempar ValueError pada kunci duplikat
import pandas as pd

df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
try:
    lebar = df.pivot(index="ruang", columns="status_sensor", values="suhu_c")
except Exception as e:
    print(type(e).__name__)
    print(e)
text Keluaran
ValueError
Index contains duplicate entries, cannot reshape

Pesan error menyatakan bahwa indeks memuat entri duplikat sehingga data tidak dapat direshape. Perilaku ini disengaja dan bukan kekurangan, karena pivot tidak memiliki aturan pemilihan nilai untuk sel yang diperebutkan lebih dari satu kandidat. Apabila data mentah masih mengandung baris ganda per kunci, pilihan alatnya bukan pivot, melainkan fungsi pada bagian berikut.

pivot_table mengagregasi baris duplikat#

pivot_table menangani pasangan kunci yang muncul lebih dari sekali dengan mengagregasinya menurut aggfunc, yang defaultnya berupa rata-rata. Demo pertama dijalankan pada kunci yang sama dengan demo error sebelumnya, kini tanpa error.

python pivot_table mengagregasi kunci duplikat dengan rata-rata
import pandas as pd

df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
tabel = df.pivot_table(index="ruang", columns="status_sensor", values="suhu_c", aggfunc="mean")
print(tabel.round(1))
text Keluaran
status_sensor  kalibrasi  normal  rusak
ruang
Lab A               23.3    23.7   25.3
Lab B               23.4    23.8   25.0
Ruang Arsip         23.4    24.4    NaN

Sel Ruang Arsip untuk status rusak berupa NaN karena tidak ada baris dengan kombinasi tersebut, bukan karena perhitungannya gagal. Perilaku agregasi pada duplikat diperjelas dengan data mini yang ditambah satu baris ganda untuk pasangan 08:00 dan Lab A.

python pivot_table pada data mini berduplikat
import pandas as pd

panjang = pd.read_csv("mini_log.csv")
mini_dup = pd.concat([
    panjang,
    pd.DataFrame({"waktu": ["08:00"], "ruang": ["Lab A"], "suhu_c": [24.1]}),
], ignore_index=True)
tabel_mini = mini_dup.pivot_table(index="waktu", columns="ruang", values="suhu_c", aggfunc="mean")
print(mini_dup)
print(tabel_mini)
text Keluaran
   waktu        ruang  suhu_c
0  08:00        Lab A    23.5
1  08:00        Lab B    22.8
2  08:00  Ruang Arsip    21.0
3  08:15        Lab A    23.9
4  08:15        Lab B    22.6
5  08:15  Ruang Arsip    20.9
6  08:00        Lab A    24.1
ruang  Lab A  Lab B  Ruang Arsip
waktu
08:00   23.8   22.8         21.0
08:15   23.9   22.6         20.9

Sel 08:00 untuk Lab A berisi 23.8, yaitu rata-rata dari 23.5 dan 24.1, sedangkan pasangan lain tetap berupa nilai tunggal. Dua parameter berikut melengkapi laporan. Parameter margins=True menambahkan baris dan kolom ringkasan dengan nama yang ditetapkan lewat margins_name, sedangkan fill_value mengganti sel NaN untuk kombinasi yang tidak punya baris.

python Margins dan fill_value pada pivot_table
import pandas as pd

panjang = pd.read_csv("mini_log.csv")
mini_dup = pd.concat([
    panjang,
    pd.DataFrame({"waktu": ["08:00"], "ruang": ["Lab A"], "suhu_c": [24.1]}),
], ignore_index=True)
mini5 = panjang.drop(index=1)
print(mini_dup.pivot_table(
    index="waktu", columns="ruang", values="suhu_c",
    aggfunc="mean", margins=True, margins_name="Semua",
))
print(mini5.pivot_table(index="waktu", columns="ruang", values="suhu_c", aggfunc="mean"))
print(mini5.pivot_table(index="waktu", columns="ruang", values="suhu_c", aggfunc="mean", fill_value=0.0))
text Keluaran
ruang      Lab A  Lab B  Ruang Arsip      Semua
waktu
08:00  23.800000   22.8        21.00  22.850000
08:15  23.900000   22.6        20.90  22.466667
Semua  23.833333   22.7        20.95  22.685714
ruang  Lab A  Lab B  Ruang Arsip
waktu
08:00   23.5    NaN         21.0
08:15   23.9   22.6         20.9
ruang  Lab A  Lab B  Ruang Arsip
waktu
08:00   23.5    0.0         21.0
08:15   23.9   22.6         20.9

Kolom Semua berisi rata-rata seluruh bacaan pada barisnya, baris Semua berisi rata-rata sekolom, dan sel pojok berisi rata-rata keseluruhan. Tabel kedua dan ketiga memperlihatkan peran fill_value pada data mini yang baris Lab B untuk pukul 08:00 dihapus darinya, yaitu sel kosong berubah dari NaN menjadi 0.0. Ringkasan semacam itu tidak perlu dihitung terpisah karena sudah tersedia dari satu panggilan.

Kesalahan umum#

Kesalahan pertama adalah memilih pivot untuk data yang punya baris ganda per kunci, misalnya log mentah yang mencatat satu ruang lebih dari sekali pada satu waktu. Akibatnya ValueError muncul dan analisis berhenti. Perbaikannya ada pada pemilihan alat, yaitu gunakan pivot_table dengan aggfunc yang sesuai konteks, atau kecilkan data menjadi kunci unik lewat agregasi terlebih dahulu sebelum diputar.

Kesalahan kedua adalah mengisi sel kosong dengan fill_value=0 pada kolom suhu, sehingga kombinasi yang tidak diukur terbaca sebagai suhu nol derajat. Nilai pengganti harus dipilih sesuai makna kolomnya, dan sering kali lebih jujur membiarkan NaN terlihat agar pembaca laporan tahu bahwa data itu memang tidak ada. Kedua kesalahan ini berpangkal pada satu hal yang sama, yaitu bentuk lebar menyembunyikan baris asli sehingga keputusan agregasi dan pengisian harus disadari sejak awal.

Ringkasan#

  • pivot menuntut pasangan (index, columns) yang unik dan melempar ValueError bila ada duplikat.
  • pivot_table mengagregasi duplikat menurut aggfunc, dengan default rata-rata, sehingga aman untuk data mentah.
  • margins=True menambah baris dan kolom ringkasan, sedangkan fill_value mengisi sel untuk kombinasi yang tidak ada.
  • Sel NaN pada hasil berarti kombinasi tidak punya baris sama sekali, dan keputusan pengisiannya menyusul lewat fill_value.

Referensi#