Mental model yang tepat membuat perilaku kode pandas dapat diprediksi sebelum kode itu dijalankan. Topik ini menetapkan model tersebut, yaitu Series sebagai kolom berlabel dan DataFrame sebagai kumpulan kolom yang berbagi index. Penjelasan diawali dari pembuatan Series berlabel, dilanjutkan penyelarasan label pada operasi antar-Series, dan ditutup dengan diagram yang merangkum hubungan array NumPy, label, dan Series. Setelah topik ini selesai, munculnya NaN pada hasil operasi dapat dijelaskan tanpa menebak.
Series: nilai beserta labelnya#
Series adalah array satu dimensi yang setiap nilainya dipasangkan dengan satu label melalui index. Dibanding array NumPy, Series menambahkan dua hal, yaitu deretan label dan nama. Deretan label memungkinkan satu nilai dicari melalui nama ruangannya, sedangkan nama Series berperan seperti nama kolom ketika Series nanti dimasukkan ke dalam tabel.
import pandas as pd
suhu = pd.Series([22.5, 23.1, 24.0], index=["Lab A", "Lab B", "Ruang Arsip"], name="suhu_c")
print(suhu)
print(suhu["Lab B"])Lab A 22.5
Lab B 23.1
Ruang Arsip 24.0
Name: suhu_c, dtype: float64
23.1Keluaran menampilkan kolom label di kiri, kolom nilai di kanan, lalu nama dan dtype di bagian akhir. Akses suhu["Lab B"] mencari nilai melalui label, sehingga perubahan urutan data tidak merusak kode yang merujuk label. Index juga menempel pada Series, artinya label ikut berpindah ketika Series disalin, disaring, atau diurutkan. Sifat inilah yang membedakan Series dari array NumPy yang hanya dikenali melalui posisinya.
Operasi menyelaraskan label#
Operasi antar-Series menyelaraskan pasangan nilai berdasarkan label indexnya dan bukan berdasarkan posisinya. Mekanisme ini disebut penyelarasan (alignment). Kedua Series diperiksa labelnya satu per satu, lalu pasangan nilai dengan label yang sama dijumlahkan. Label yang hanya dimiliki salah satu Series tidak menemukan pasangannya, sehingga hasilnya ditandai NaN sebagai penanda nilai hilang (missing value).
import pandas as pd
pagi = pd.Series([22.5, 23.1], index=["Lab A", "Lab B"])
siang = pd.Series([24.0, 24.8, 25.1], index=["Lab A", "Lab B", "Ruang Arsip"])
hasil = pagi + siang
print(hasil)Lab A 46.5
Lab B 47.9
Ruang Arsip NaN
dtype: float64Ruang Arsip hanya tercatat pada pembacaan siang, sehingga penjumlahannya tidak menemukan pasangan dan menghasilkan NaN. Perilaku ini berbeda dengan penjumlahan array NumPy yang mencocokkan posisi, yaitu elemen ke-0 dengan elemen ke-0. Pada penyelarasan label, urutan data boleh berbeda dan hasilnya tetap benar.
import pandas as pd
a = pd.Series([1.0, 2.0], index=["Lab A", "Lab B"])
b = pd.Series([10.0, 20.0], index=["Lab B", "Lab A"])
print(a + b)Lab A 21.0
Lab B 12.0
dtype: float64Kedua Series di atas memuat label yang sama dalam urutan terbalik. Penjumlahannya tetap menghitung 1.0 + 20.0 untuk Lab A dan 2.0 + 10.0 untuk Lab B karena pencocokan dilakukan melalui label. Baris dtype pada keluaran tetap tampil, sedangkan baris Name hilang karena kedua Series yang dijumlahkan tidak membawa nama.
DataFrame: kolom berbagi index#
DataFrame menyusun beberapa kolom nilai di atas satu index yang sama, dan setiap kolomnya tetap berperilaku sebagai Series. Struktur ini membuat tabel dan kolomnya memiliki bahasa yang sama, sehingga mekanisme label yang sudah dijelaskan berlaku pada kedua tingkat tersebut.
import pandas as pd
df = pd.DataFrame({
"suhu_c": [22.5, 23.1, 24.0],
"lembap_pct": [55.0, 61.2, 48.9],
}, index=["Lab A", "Lab B", "Ruang Arsip"])
print(df)
s = df["suhu_c"]
print(s)
print(s.index)
print(df.index)
print(df.columns) suhu_c lembap_pct
Lab A 22.5 55.0
Lab B 23.1 61.2
Ruang Arsip 24.0 48.9
Lab A 22.5
Lab B 23.1
Ruang Arsip 24.0
Name: suhu_c, dtype: float64
Index(['Lab A', 'Lab B', 'Ruang Arsip'], dtype='str')
Index(['Lab A', 'Lab B', 'Ruang Arsip'], dtype='str')
Index(['suhu_c', 'lembap_pct'], dtype='str')Seleksi df["suhu_c"] mengembalikan Series dengan nama, nilai, dan index yang persis sama dengan kolom asalnya. Karena seluruh kolom berbagi index yang sama, penyelarasan label yang bekerja pada operasi antar-Series berlaku juga di dalam satu DataFrame, misalnya ketika dua kolom dijumlahkan. Kerangka tabel dengan demikian tersusun atas dua deretan label, yaitu index untuk baris dan nama untuk kolom. Keduanya diperiksa melalui df.index dan df.columns, dan keduanya dikelola dengan mekanisme label yang sama.
Diagram array berlabel#
Diagram berikut merangkum mental model array berlabel yang digunakan sepanjang jalur ini. Sisi kiri menampilkan array NumPy yang hanya menyimpan tiga nilai. Satu-satunya identitas pada array itu adalah posisi, sehingga nilai 22.5 hanya dapat dirujuk sebagai elemen pertama. Sisi kanan menampilkan Series yang terdiri atas dua bagian, yaitu deretan label index dan deretan nilai. Pasangan keduanya membentuk satu kolom berlabel, dan DataFrame kemudian menumpuk beberapa Series berlabel yang berbagi deretan index yang sama.
Model ini menjadi dasar bagi seleksi dengan loc pada modul Seleksi, agregasi per ruangan pada modul GroupBy, dan penggabungan tabel pada modul Penggabungan Data. Seleksi berjalan melalui label, sehingga df.loc merujuk nama baris dan bukan posisinya. Penyelarasan berjalan melalui label, sehingga operasi antarkolom tidak terganggu oleh perbedaan urutan. Selama model array berlabel ini dipegang, perilaku tersebut dapat diprediksi langsung dari bentuk datanya.
Kesalahan umum#
Dua kesalahan yang paling sering terjadi pada tahap ini adalah menganggap operasi Series berbasis posisi dan mengubah hasil seleksi sambil berharap tabel aslinya ikut berubah. Keduanya tidak menampilkan pesan error, sehingga hasilnya baru disadari ketika analisis sudah berlanjut.
Kesalahan yang pertama muncul ketika penjumlahan dua Series menghasilkan NaN padahal kedua Series terlihat berisi data. Penyebabnya adalah label yang tidak cocok, misalnya "Lab A" pada satu Series tertulis "Lab A " dengan spasi tambahan, sehingga pencocokan gagal tanpa terlihat. Perbaikannya dilakukan dengan menampilkan kedua index melalui print terlebih dahulu, lalu menyetarakan penulisan labelnya sebelum operasi dijalankan.
Kesalahan yang kedua terjadi pada pengubahan nilai melalui hasil seleksi. Pada pandas 3, mekanisme Copy-on-Write selalu aktif, sehingga hasil seleksi merupakan salinan dan pengubahannya tidak menjalar ke DataFrame asal.
import pandas as pd
df = pd.DataFrame({"suhu_c": [22.5, 23.1]})
s = df["suhu_c"]
s[0] = 99.0
print(df) suhu_c
0 22.5
1 23.1Nilai pada df tetap 22.5 meskipun s sudah diisi 99.0. Pengubahan dilakukan melalui DataFrame-nya langsung, yaitu melalui df.loc untuk satu sel atau melalui df["kolom"] = ... untuk satu kolom penuh.
import pandas as pd
df = pd.DataFrame({"suhu_c": [22.5, 23.1]})
df.loc[0, "suhu_c"] = 99.0
print(df) suhu_c
0 99.0
1 23.1Pola df.loc[...] = ... dan df["kolom"] = ... menjadi bentuk pengubahan yang digunakan sepanjang jalur ini. Bentuk tersebut membuat sasaran setiap pengubahan tertulis secara eksplisit, sehingga akibatnya mudah dilacak pada saat kode ditinjau kembali.
Ringkasan#
- Series memasangkan nilai array satu dimensi dengan deretan label index, sehingga nilai dicari melalui label dan bukan melalui posisi.
- Operasi antar-Series menyelaraskan nilai berdasarkan label, dan label tanpa pasangan menghasilkan
NaN. - DataFrame menumpuk beberapa kolom Series di atas satu index yang sama, yang diperiksa melalui
df.indexdandf.columns. - Copy-on-Write membuat hasil seleksi menjadi salinan, sehingga pengubahan nilai dilakukan melalui
df.locataudf["kolom"] = ....
Referensi#
- Intro to data structures — pandas documentation — pengenalan resmi Series, DataFrame, dan index.
- 10 minutes to pandas — pandas documentation — tur resmi yang memuat penyelarasan label dan operasi dasar antar-Series.
- Migration Guides — pandas documentation — rincian Copy-on-Write yang selalu aktif pada pandas 3.