Analisis jarang memproses seluruh baris dan kolom sekaligus. Topik ini membahas tiga cara mengambil subset data pada pandas, yaitu loc untuk seleksi berbasis label, iloc untuk seleksi berbasis posisi, dan masker boolean, yakni deret nilai True dan False yang digunakan untuk menyaring baris berdasarkan syarat. Setelah topik ini, baris dan kolom yang relevan dapat diambil dengan tepat, dan kesalahan seleksi yang paling sering terjadi dapat dihindari.
Data contoh dan index#
Setiap baris pada DataFrame menempel pada sebuah label yang disebut index, yakni penanda baris yang digunakan untuk seleksi. Tanpa pengaturan, labelnya berupa angka mulai dari nol. Untuk memperjelas perbedaan antara loc dan iloc, data contoh pada topik ini menggunakan label huruf, yaitu s1 sampai s6.
import pandas as pd
nilai = pd.DataFrame(
{
"nama": ["Ali", "Budi", "Citra", "Dewi", "Eka", "Fajar"],
"kelas": ["7A", "7A", "7B", "7B", "8A", "8A"],
"matematika": [78, 85, 90, 76, 88, 92],
"bahasa": [82, 79, 88, 81, 90, 84],
},
index=["s1", "s2", "s3", "s4", "s5", "s6"],
)
print(nilai) nama kelas matematika bahasa
s1 Ali 7A 78 82
s2 Budi 7A 85 79
s3 Citra 7B 90 88
s4 Dewi 7B 76 81
s5 Eka 8A 88 90
s6 Fajar 8A 92 84Label index inilah yang digunakan loc, sedangkan iloc menggunakan posisi urut baris. Pada data yang dimuat dari berkas, labelnya biasanya berupa angka, sehingga label dan posisinya kebetulan identik. Data contoh ini sengaja membuat keduanya berbeda agar perbedaan mekanismenya terlihat.
Seleksi dengan loc#
loc menerima label. Ekspresi nilai.loc["s2"] mengambil satu baris berlabel s2 dan mengembalikannya sebagai Series, sedangkan nilai.loc["s2", "matematika"] mengambil satu sel pada pertemuan baris s2 dan kolom matematika. Pemotongan rentang dengan loc bersifat inklusif, sehingga batas akhirnya ikut diambil.
import pandas as pd
nilai = pd.DataFrame(
{
"nama": ["Ali", "Budi", "Citra", "Dewi", "Eka", "Fajar"],
"kelas": ["7A", "7A", "7B", "7B", "8A", "8A"],
"matematika": [78, 85, 90, 76, 88, 92],
"bahasa": [82, 79, 88, 81, 90, 84],
},
index=["s1", "s2", "s3", "s4", "s5", "s6"],
)
print(nilai.loc["s2"])
print()
print(nilai.loc["s2", "matematika"])
print()
print(nilai.loc["s1":"s3"])nama Budi
kelas 7A
matematika 85
bahasa 79
Name: s2, dtype: object
85
nama kelas matematika bahasa
s1 Ali 7A 78 82
s2 Budi 7A 85 79
s3 Citra 7B 90 88Rentang s1 sampai s3 menghasilkan tiga baris, berbeda dengan pemotongan list pada Python yang mengabaikan batas akhirnya. Perilaku inklusif ini berlaku karena batas rentang loc adalah label, bukan posisi. Selain label tunggal, loc juga menerima daftar label, misalnya nilai.loc[["s1", "s4"]] untuk mengambil dua baris yang tidak berurutan, dan nama kolom dapat ditulis pada dimensi keduanya untuk membatasi kolom yang diambil.
Seleksi dengan iloc#
iloc menerima posisi, yaitu urutan baris mulai dari nol. Ekspresi nilai.iloc[1] mengambil baris kedua, dan hasilnya sama dengan nilai.loc["s2"] karena baris kedua berlabel s2 pada data contoh ini. Pemotongan rentang dengan iloc mengikuti konvensi Python dan bersifat eksklusif, sehingga batas akhirnya tidak ikut diambil.
import pandas as pd
nilai = pd.DataFrame(
{
"nama": ["Ali", "Budi", "Citra", "Dewi", "Eka", "Fajar"],
"kelas": ["7A", "7A", "7B", "7B", "8A", "8A"],
"matematika": [78, 85, 90, 76, 88, 92],
"bahasa": [82, 79, 88, 81, 90, 84],
},
index=["s1", "s2", "s3", "s4", "s5", "s6"],
)
print(nilai.iloc[1])
print()
print(nilai.iloc[:3, 1:3])nama Budi
kelas 7A
matematika 85
bahasa 79
Name: s2, dtype: object
kelas matematika
s1 7A 78
s2 7A 85
s3 7B 90Rentang :3 pada dimensi baris berarti posisi 0, 1, dan 2, sedangkan rentang 1:3 pada dimensi kolom berarti kolom kedua dan ketiga, yaitu kelas dan matematika. Dengan demikian, iloc[:3, 1:3] mengambil blok data tiga baris kali dua kolom tanpa kolom nama dan bahasa. Aturan memilihnya sederhana, yaitu loc bila label barisnya diketahui dan iloc bila posisinya yang diketahui, misalnya lima baris pertama atau baris terakhir.
Penyaringan dengan masker boolean#
Perbandingan pada satu kolom menghasilkan masker boolean, yaitu deret nilai True dan False dengan panjang yang sama dengan jumlah baris. Masker yang diberikan di dalam kurung siku memilih baris yang bernilai True.
import pandas as pd
nilai = pd.DataFrame(
{
"nama": ["Ali", "Budi", "Citra", "Dewi", "Eka", "Fajar"],
"kelas": ["7A", "7A", "7B", "7B", "8A", "8A"],
"matematika": [78, 85, 90, 76, 88, 92],
"bahasa": [82, 79, 88, 81, 90, 84],
},
index=["s1", "s2", "s3", "s4", "s5", "s6"],
)
masker = nilai["matematika"] >= 80
print(masker)
print()
print(nilai[masker])s1 False
s2 True
s3 True
s4 False
s5 True
s6 True
Name: matematika, dtype: bool
nama kelas matematika bahasa
s2 Budi 7A 85 79
s3 Citra 7B 90 88
s5 Eka 8A 88 90
s6 Fajar 8A 92 84Keluaran pertama adalah maskernya sendiri, yaitu enam nilai boolean yang menyatakan baris dengan nilai matematika minimal 80. Keluaran kedua adalah hasil penyaringannya, berupa empat baris yang labelnya tidak berurutan karena baris s1 dan s4 terbuang. Label tetap asli, sehingga jejak baris asalnya tidak hilang. Penyaringan dengan beberapa syarat menggabungkan masker menggunakan operator & untuk syarat “dan” dan | untuk syarat “atau”, dengan setiap syarat diberi tanda kurung.
import pandas as pd
nilai = pd.DataFrame(
{
"nama": ["Ali", "Budi", "Citra", "Dewi", "Eka", "Fajar"],
"kelas": ["7A", "7A", "7B", "7B", "8A", "8A"],
"matematika": [78, 85, 90, 76, 88, 92],
"bahasa": [82, 79, 88, 81, 90, 84],
},
index=["s1", "s2", "s3", "s4", "s5", "s6"],
)
pilihan = (nilai["kelas"] == "7A") & (nilai["matematika"] >= 80)
print(nilai[pilihan]) nama kelas matematika bahasa
s2 Budi 7A 85 79Tanda kurung wajib karena operator & memiliki urutan pengerjaan yang lebih tinggi daripada perbandingan ==. Tanpa kurung, Python menghitung "7A" & nilai["matematika"] terlebih dahulu dan memunculkan error. Syarat gabungan juga dapat dipadukan dengan loc untuk membatasi kolomnya sekaligus, misalnya nilai.loc[pilihan, ["nama", "matematika"]], karena loc menerima masker pada dimensi barisnya.
Kesalahan umum#
Kesalahan pertama adalah menggunakan kata kunci and dan or dari Python pada masker. Kata kunci tersebut menuntut nilai boolean tunggal, sedangkan masker berisi banyak nilai sekaligus, dan permintaan itu tidak dapat dijawab.
import pandas as pd
nilai = pd.DataFrame(
{
"nama": ["Ali", "Budi", "Citra", "Dewi", "Eka", "Fajar"],
"kelas": ["7A", "7A", "7B", "7B", "8A", "8A"],
"matematika": [78, 85, 90, 76, 88, 92],
"bahasa": [82, 79, 88, 81, 90, 84],
},
index=["s1", "s2", "s3", "s4", "s5", "s6"],
)
try:
pilihan = (nilai["kelas"] == "7A") and (nilai["matematika"] >= 80)
except ValueError as e:
print("ValueError:", e)ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().Pesan errornya menyebut kata “ambiguous” karena benar atau salahnya sebuah deret nilai memang tidak terdefinisi. Ganti kata kunci tersebut dengan operator & dan | beserta tanda kurung per syarat.
Kesalahan kedua adalah penulisan berantai untuk mengubah data. Ekspresi nilai[nilai["kelas"] == "8A"]["bahasa"] = 90 terlihat wajar, tetapi pandas tidak menjamin perubahan itu diterapkan pada data asli, dan pandas menampilkan peringatan SettingWithCopyWarning ketika pola ini digunakan. Cara yang dijamin adalah satu panggilan loc dengan masker dan nama kolom.
import pandas as pd
nilai = pd.DataFrame(
{
"nama": ["Ali", "Budi", "Citra", "Dewi", "Eka", "Fajar"],
"kelas": ["7A", "7A", "7B", "7B", "8A", "8A"],
"matematika": [78, 85, 90, 76, 88, 92],
"bahasa": [82, 79, 88, 81, 90, 84],
},
index=["s1", "s2", "s3", "s4", "s5", "s6"],
)
salinan = nilai.copy()
salinan.loc[salinan["kelas"] == "8A", "bahasa"] = 90
print(salinan) nama kelas matematika bahasa
s1 Ali 7A 78 82
s2 Budi 7A 85 79
s3 Citra 7B 90 88
s4 Dewi 7B 76 81
s5 Eka 8A 88 90
s6 Fajar 8A 92 90Pola di atas menyalin seluruh tabel lebih dahulu, lalu mengubah kolom bahasa untuk baris kelas 8A pada salinan itu. Apabila subset memang dimaksudkan sebagai tabel mandiri, tambahkan .copy() pada akhir penyaringannya, misalnya nilai[nilai["kelas"] == "8A"].copy(), sehingga hasilnya terlepas dari data aslinya dan bebas dari peringatan tersebut.
Ringkasan#
locbekerja dengan label dan rentangnya inklusif, sedangkanilocbekerja dengan posisi dan rentangnya eksklusif.- Masker boolean memilih baris berdasarkan syarat, digabung dengan
&dan|serta tanda kurung per syarat, dan label barisnya tetap asli setelah penyaringan. - Pengubahan data bersyarat dilakukan melalui satu panggilan
locdengan masker dan nama kolom, bukan penulisan berantai.
Referensi#
- pandas user guide — Pandas — Panduan resmi pandas yang memuat bagian indexing dan seleksi data.
- pandas documentation — Pandas — Pintu masuk dokumentasi resmi pandas beserta API reference-nya.