stack dan unstack

Manuver level index dengan stack dan unstack untuk membentuk ulang tabel.

Daftar isi

Fungsi stack dan unstack mengubah bentuk tabel dengan memindahkan level antara indeks baris dan kolom, tanpa menjadikan kolom biasa sebagai sumber manuver. Topik ini membahas pembentukan MultiIndex dengan set_index, pemakaian unstack beserta perbandingannya dengan pivot, pemakaian stack, serta kepulangan ke tabel datar lewat reset_index. Data yang digunakan kembali adalah data mini enam baris log sensor.

unstack memindahkan level indeks menjadi kolom#

Fungsi unstack memindahkan satu level indeks baris menjadi level kolom, sehingga tabel yang menjulur ke bawah berubah melebar ke samping. Bahan manuvernya adalah indeks bertingkat, yaitu MultiIndex, yang dibentuk dengan set_index(["waktu", "ruang"]). Jalankan blok berikut dan bandingkan hasil unstack dengan hasil pivot pada data yang sama.

python unstack dibandingkan pivot pada data yang sama
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
mini_lebar = panjang.pivot(index="waktu", columns="ruang", values="suhu_c")
terindeks = panjang.set_index(["waktu", "ruang"])
lebar_unstack = terindeks.unstack("ruang")
print(mini_lebar)
print(lebar_unstack)
print(lebar_unstack.equals(mini_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
      suhu_c
ruang  Lab A Lab B Ruang Arsip
waktu
08:00   23.5  22.8        21.0
08:15   23.9  22.6        20.9
False

Angka pada kedua tabel sama persis, tetapi equals mengembalikan False karena strukturnya berbeda. Hasil unstack memakai kepala kolom bertingkat, yaitu nama kolom data suhu_c berada di atas nama ruang, sedangkan hasil pivot berkepala kolom datar dengan level bernama ruang. Perbedaan itu berasal dari sumber manuvernya, karena unstack menggerakkan level indeks sehingga identitas kolom data ikut terbawa di atasnya.

Perbandingan unstack dengan pivot#

Kedua fungsi menghasilkan tabel lebar dengan isi yang serupa, tetapi jalurnya berbeda dan hasilnya tidak selalu identik secara struktur. pivot bekerja dari kolom biasa pada tabel datar, sedangkan unstack bekerja dari level indeks baris pada tabel yang sudah terindeks. Perbedaannya dirangkum sebagai berikut:

Aspekpivotunstack
Sumber label kolom barunilai unik kolom biasalevel indeks baris
Kepala kolom hasildatar dengan level bernamabertingkat di bawah nama kolom data
Kunci duplikatmelempar ValueErrortidak terjadi karena pasangan level indeks sudah unik

Pemilihan alatnya mengikuti bentuk awal data. Apabila data masih datar seperti tabel hasil pembacaan CSV, pivot lebih langsung karena tidak perlu set_index terlebih dahulu. Apabila data sudah diindeks berjenjang, misalnya setelah set_index untuk pencarian cepat, unstack memanfaatkan indeks yang sudah ada tanpa membangun ulang strukturnya. Akses kolom pada hasil unstack pun bertingkat, misalnya lebar_unstack["suhu_c", "Lab A"] menghasilkan deret suhu untuk Lab A. Kesadaran akan perbedaan struktur ini mencegah keheranan ketika equals mengembalikan False padahal angkanya sama.

stack mengembalikan kolom menjadi level indeks terbawah#

Fungsi stack adalah kebalikan unstack, yaitu memindahkan kepala kolom menjadi level indeks terbawah sehingga tabel memanjang kembali. Hasilnya bukan DataFrame, melainkan Series ber-MultiIndex karena seluruh kolom dilebur menjadi satu deret nilai. Susun kembali tabel berindeks dari berkas mini, lalu tumpuk kolomnya.

python stack mengembalikan kolom menjadi level indeks
import pandas as pd

lebar_unstack = pd.read_csv("mini_log.csv").set_index(["waktu", "ruang"]).unstack("ruang")
print(lebar_unstack.stack())
text Keluaran
                   suhu_c
waktu ruang
08:00 Lab A          23.5
      Lab B          22.8
      Ruang Arsip    21.0
08:15 Lab A          23.9
      Lab B          22.6
      Ruang Arsip    20.9

Level ruang kini menjadi level terbawah indeks, tepat di bawah waktu, dan label suhu_c tetap tampil sebagai nama deretnya. Susunan barisnya mengikuti urutan kolom pada tabel lebarnya, yaitu untuk setiap waktu, kolom-kolom ruang ditumpuk berurutan. Bentuk ini siap dijadikan bahan operasi indeks pada topik seleksi karena semua labelnya berada pada indeks, bukan pada kepala kolom.

Kembali ke tabel datar dengan reset_index#

Fungsi reset_index memindahkan setiap level indeks menjadi kolom biasa, sehingga hasil stack kembali menjadi tabel datar dengan kolom yang dikenali semua fungsi DataFrame. Jalankan blok berikut dan periksa kesamaannya dengan tabel panjang awal.

python reset_index mengembalikan hasil stack ke tabel datar
import pandas as pd

panjang = pd.read_csv("mini_log.csv")
datar = panjang.set_index(["waktu", "ruang"]).unstack("ruang").stack().reset_index()
print(datar)
print(datar.equals(panjang))
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
True

Nilai equals sekarang True tanpa pengurutan tambahan karena urutan baris hasil stack kebetulan sama dengan urutan tabel panjang awal, yaitu terurut waktu kemudian ruang. Rangkaian set_index, unstack, stack, dan reset_index dengan demikian membentuk satu siklus tertutup yang kembali ke titik asalnya. Siklus ini berguna sebagai uji kesehatan pemahaman, karena satu arah yang keliru di tengah jalan akan langsung terlihat pada equals.

Kesalahan umum#

Kesalahan yang paling sering adalah tertukarnya arah, yaitu menjalankan stack ketika tabel justru harus melebar atau sebaliknya. Arah kedua fungsi dirangkum pada tabel berikut.

FungsiArah pergerakan level
unstacklevel indeks baris menjadi kolom
stackkepala kolom menjadi level indeks terbawah

Akibat arah yang keliru bersifat langsung, yaitu tabel yang diharapkan melebar justru memanjang menjadi deret panjang, atau operasi berhenti dengan pesan error karena level yang diminta tidak ada. Kesalahan kedua adalah memperlakukan hasil stack sebagai tabel biasa, misalnya memanggil hasil["ruang"] padahal hasilnya Series berindeks bertingkat, sehingga muncul KeyError. Perbaikannya konsisten, yaitu panggil reset_index terlebih dahulu ketika kolom biasa dibutuhkan, dan simpan bentuk berindeks hanya selama operasi indeks masih berlangsung.

Ringkasan#

  • set_index(["waktu", "ruang"]) membentuk MultiIndex dua level sebagai bahan manuver stack dan unstack.
  • unstack memindahkan level indeks menjadi kolom, sedangkan stack mengembalikan kepala kolom menjadi level indeks terbawah.
  • Hasil unstack berkepala kolom bertingkat, sehingga strukturnya berbeda dari pivot meskipun angkanya sama.
  • reset_index mengembalikan hasil manuver menjadi tabel datar yang setara dengan tabel panjang awal.

Referensi#