Chapter sebelumnya membuat MultiIndex dan melakukan akses dari level terluar ke dalam. Kebutuhan analisis sering berbalik arah: kita ingin melompat ke level mana pun, misalnya “tampilkan semua cabang pada bulan 1 saja” atau “tukar urutan level agar laporan terbaca per kategori”. Chapter ini membahas alat navigasi level: xs() untuk mengambil cross-section satu level, swaplevel() dan reorder_levels() untuk menyusun ulang posisi level, droplevel() untuk membuang level, serta pemeriksaan isi level lewat get_level_values(). Dataset penjualan 27 baris dari chapter sebelumnya tetap kita pakai.
xs(): Cross-Section pada Level Mana Pun #
Method xs() mengambil potongan data pada satu level tanpa menyentuh level lain, seperti pemotongan lintas pada kue berlapis — sisi yang dipotong hilang dari hasil. Script berikut memakai dataset yang sama dan menunjukkan varian pemanggilannya.
import pandas as pd
kota_list = ["Jakarta", "Bandung", "Surabaya"]
bulan_list = [1, 2, 3]
kategori_list = ["Elektronik", "Pakaian", "Makanan"]
dasar = {"Elektronik": 420, "Pakaian": 260, "Makanan": 150}
baris = []
for kota in kota_list:
for bulan in bulan_list:
for kategori in kategori_list:
omzet = dasar[kategori] + 30 * kota_list.index(kota) + 12 * (bulan - 1)
baris.append((kota, bulan, kategori, omzet))
penjualan = pd.DataFrame(baris, columns=["kota", "bulan", "kategori", "omzet"])
multi = penjualan.set_index(["kota", "bulan", "kategori"]).sort_index()
# xs() tanpa level eksplisit: seleksi pada level terluar
print(multi.xs("Bandung"))
print()
# xs() dengan level nama: seleksi di level mana pun
print(multi.xs(1, level="bulan").head(5))
print()
# drop_level=False: level yang diseleksi tetap ada di hasil
print(multi.xs("Bandung", drop_level=False).head(3))
print()
# xs() dengan tuple pada beberapa level sekaligus
print(multi.xs(("Jakarta", 2), level=["kota", "bulan"]))
print()
# swaplevel: tukar posisi dua level, lalu sort_index merapikan
print(multi.swaplevel().sort_index().head(4))
print()
# reorder_levels: susun ulang urutan semua level
print(multi.reorder_levels(["bulan", "kategori", "kota"]).sort_index().head(4))
print()
# droplevel: buang satu level dari index
print(multi.droplevel("kategori").head(4))
print()
# memeriksa isi level
print("label unik kategori :", multi.index.get_level_values("kategori").unique().tolist())
print("isi levels[0] (kota) :", multi.index.levels[0].tolist())Output yang Dihasilkan:
omzet
bulan kategori
1 Elektronik 450
Makanan 180
Pakaian 290
2 Elektronik 462
Makanan 192
Pakaian 302
3 Elektronik 474
Makanan 204
Pakaian 314
omzet
kota kategori
Bandung Elektronik 450
Makanan 180
Pakaian 290
Jakarta Elektronik 420
Makanan 150
omzet
kota bulan kategori
Bandung 1 Elektronik 450
Makanan 180
Pakaian 290
omzet
kategori
Elektronik 432
Makanan 162
Pakaian 272
omzet
kota kategori bulan
Bandung Elektronik 1 450
2 462
3 474
Makanan 1 180
omzet
bulan kategori kota
1 Elektronik Bandung 450
Jakarta 420
Surabaya 480
Makanan Bandung 180
omzet
kota bulan
Bandung 1 450
1 180
1 290
2 462
label unik kategori : ['Elektronik', 'Makanan', 'Pakaian']
isi levels[0] (kota) : ['Bandung', 'Jakarta', 'Surabaya']Mari kita bedah bagian pentingnya:
- Baris 19 (
xs("Bandung")): tanpa argumenlevel,xs()menyeleksi level terluar; hasilnya sembilan baris Bandung dengan levelkotasudah tidak ada di index, tersisabulandankategori. - Baris 23 (
level="bulan"): argumenlevelmenerima nama maupun posisi angka, sehingga seleksi bisa dilakukan di level mana pun; kelima baris pertama menunjukkan kotaBandungdanJakartauntuk bulan 1. - Baris 27 (
drop_level=False): level yang diseleksi dipertahankan di hasil, berguna ketika hasil akan digabung kembali dengan data lain yang masih membawa label tersebut. - Baris 31 (tuple dua level):
leveljuga menerima list, sehinggaxs(("Jakarta", 2), level=["kota", "bulan"])mengambil tiga baris kategori untuk kombinasi Jakarta–bulan 2 sekaligus.
Menukar dan Menyusun Ulang Level #
swaplevel() menukar posisi dua level, secara default level 0 dan level 1; hasilnya terlihat pada tampilan output kelima, tempat bulan kini menjadi level terluar dan kategori berpindah ke tengah. Nilai 450, 462, 474 pada tiga baris pertamanya adalah omzet Elektronik Bandung untuk bulan 1 sampai 3, bukti bahwa data tidak berubah — hanya susunan labelnya. Method reorder_levels() lebih umum: satu list menentukan urutan seluruh level sekaligus, seperti tampilan output keenam yang memajukan bulan ke posisi pertama. Keduanya tidak mengurutkan baris, jadi pemanggilan sort_index() setelahnya adalah pola yang sebaiknya menjadi kebiasaan bila data akan diirisan lagi.
Membuang Level dan Memeriksa Isinya #
droplevel("kategori") menghapus satu level dan menyisakan index dua level; perhatikan pada output bahwa pasangan Bandung, 1 kini muncul tiga kali karena tiga kategori sebelumnya membedakan baris-baris itu. Label duplikat seperti ini sah dalam pandas, tetapi seleksi .loc menjadi mengembalikan beberapa baris sekaligus. Untuk pemeriksaan isi, get_level_values("kategori").unique() mengembalikan label unik sesuai urutan kemunculan di data, sedangkan index.levels[0] selalu menyimpan label level terluar dalam urutan leksikografis.
Dengan navigasi level di tangan, satu-satunya alat seleksi bertingkat yang belum kita kuasai adalah irisan dan kombinasi beberapa level sekaligus pada .loc. Chapter berikutnya menutup celah itu dengan IndexSlice, slicer resmi pandas untuk MultiIndex, beserta aturan urutan index yang menyertainya.
Referensi resmi untuk chapter ini: user guide MultiIndex / Advanced Indexing , pandas.DataFrame.xs , dan pandas.DataFrame.swaplevel .
Index bertingkat membuka satu risiko baru: label yang sama muncul lebih dari satu kali tanpa peringatan apa pun. Chapter berikutnya membahas cara mengenali label duplikat dan melarangnya lewat set_flags(allows_duplicate_labels=False).