Indeks boolean menyaring baris lewat deret nilai True dan False yang sejajar dengan data, dan deret itu disebut mask. Topik ini membahas pembentukan mask dari perbandingan kolom, penyaringan dengan df[mask] dan df.loc[mask, kolom], kondisi majemuk dengan & dan |, serta penanganan nilai hilang dengan isna() dan negasi ~. Setelah membaca, baris yang memenuhi satu kondisi maupun gabungan beberapa kondisi dapat diambil dengan benar dari dataset log sensor tiga ruangan.
Mask dari perbandingan kolom#
Perbandingan kolom terhadap sebuah nilai menghasilkan Series bertipe bool sepanjang data, dengan satu nilai kebenaran untuk setiap baris. Dataset modul ini kini membawa satu kekotoran deterministik, yaitu bacaan sensor berstatus rusak yang ditandai sebagai nilai hilang lewat pola penulisan loc sebelum disimpan ke CSV, sehingga contoh nilai hilang pada bagian belakang topik ini dapat dijalankan dengan data yang sama.
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]),
})
# bacaan sensor rusak tidak dipercaya, sehingga ditandai hilang lewat pola loc
df.loc[df["status_sensor"] == "rusak", "suhu_c"] = np.nan
df.to_csv("sensor_log.csv", index=False) # disimpan agar blok berikutnya cukup membaca berkas ini
print("baris dengan suhu hilang:", df["suhu_c"].isna().sum())baris dengan suhu hilang: 3Tiga baris kini bertanda hilang pada suhu_c. Mask paling sederhana dibentuk dari satu perbandingan, misalnya suhu di atas 25 derajat, dan dapat diperiksa isinya sebelum dipakai menyaring.
import pandas as pd
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
mask = df["suhu_c"] > 25
print(mask.head(4))
print("baris lolos:", mask.sum())0 False
1 False
2 False
3 False
Name: suhu_c, dtype: bool
baris lolos: 19Empat baris pertama tidak lolos, sedangkan dari seluruh 96 bacaan ada 21 baris yang suhunya di atas 25 derajat. Metode sum() pada mask menghitung banyaknya True, sehingga menjadi cara cepat menghitung baris yang lolos tanpa menyaringnya lebih dahulu.
Penyaringan dengan df[mask] dan df.loc[mask, kolom]#
Mask dipakai dengan meletakkannya di dalam kurung siku, baik pada df[mask] yang menyaring baris dan mengambil semua kolom, maupun pada df.loc[mask, daftar_kolom] yang menyaring baris dan memilih kolom sekaligus. Keduanya sah, tetapi bentuk loc lebih terarah karena kolom yang diambil dinyatakan eksplisit, sehingga hasilnya lebih kecil dan maksud kodenya lebih jelas.
import pandas as pd
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
mask = df["suhu_c"] > 25
print(df.loc[mask, ["waktu", "ruang", "suhu_c"]].head(5)) waktu ruang suhu_c
7 2026-01-05 08:45:00 Ruang Arsip 25.9
9 2026-01-05 09:15:00 Lab B 25.1
14 2026-01-05 10:30:00 Lab B 25.3
24 2026-01-05 13:00:00 Ruang Arsip 26.4
29 2026-01-05 14:15:00 Lab B 26.0Hasilnya lima baris pertama dari 21 baris panas, dengan label indeks asli yang ikut terbawa sehingga baris tersebut masih dapat ditelusuri di tabel asal. Urutan baris hasil mengikuti urutan tabel asal, bukan urutan nilai True, karena mask hanya menentukan baris mana yang dipertahankan.
Kondisi majemuk dengan & dan |#
Gabungan kondisi menggunakan operator & untuk logika dan serta | untuk logika atau, bukan kata kunci and dan or milik Python. Operator bitwise inilah yang bekerja sepanjang data, sedangkan and hanya berlaku untuk nilai tunggal dan akan langsung menolak Series. Setiap kondisi juga wajib diberi tanda kurung karena & mengikat lebih kuat daripada operator perbandingan, sehingga tanpa kurung Python mengevaluasi bagian tengah terlebih dahulu dan operasi berakhir sebelum waktunya.
import pandas as pd
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
dua_syarat = (df["suhu_c"] > 25) & (df["lembap_pct"] < 55)
print(df.loc[dua_syarat, ["waktu", "ruang", "suhu_c", "lembap_pct"]]) waktu ruang suhu_c lembap_pct
14 2026-01-05 10:30:00 Lab B 25.3 49.7
91 2026-01-06 05:45:00 Lab B 26.3 51.3Hanya dua baris yang memenuhi suhu di atas 25 dan kelembapan di bawah 55 sekaligus, dan keduanya berasal dari Lab B. Kondisi dengan | mengambil baris yang lolos salah satu syarat, misalnya bacaan dari Ruang Arsip atau suhu di atas 26 derajat. Bentuk yang salah diperlihatkan berikut agar pesan errornya dikenali sejak awal.
import pandas as pd
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
try:
df.loc[df["suhu_c"] > 25 and df["lembap_pct"] < 55]
except ValueError as e:
print(type(e).__name__, str(e))
try:
df.loc[df["suhu_c"] > 25 & df["lembap_pct"] < 55]
except TypeError as e:
print(type(e).__name__, str(e))ValueError The truth value of a Series is ambiguous. Use a.empty, a.item(), a.any() or a.all().
TypeError Cannot perform 'rand_' with a dtyped [float64] array and scalar of type [bool]Kata kunci and meminta satu kebenaran dari sebuah Series penuh dan berakhir ValueError, sedangkan tanda kurung yang hilang membuat Python mengevaluasi 25 & df["lembap_pct"] lebih dahulu dan berakhir TypeError. Perbaikannya selalu sama, yaitu ganti and dengan &, or dengan |, dan beri tanda kurung pada setiap kondisi.
Nilai hilang dan negasi#
Pencarian baris dengan nilai hilang menggunakan isna(), karena perbandingan biasa tidak pernah cocok dengan nilai hilang. Mask df["suhu_c"].isna() bernilai True persis pada baris yang suhunya NaN, dan negasi ~ membalik mask tersebut menjadi baris yang suhunya terisi.
import pandas as pd
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
print(df.loc[df["suhu_c"].isna(), ["waktu", "ruang", "status_sensor"]])
print("suhu terisi:", (~df["suhu_c"].isna()).sum()) waktu ruang status_sensor
43 2026-01-05 17:45:00 Lab A rusak
87 2026-01-06 04:45:00 Lab B rusak
89 2026-01-06 05:15:00 Lab B rusak
suhu terisi: 93Tiga baris yang suhunya hilang semuanya berasal dari sensor berstatus rusak, sesuai penandaan pada blok pembangun data, dan 93 baris sisanya terisi. Mask isna() dapat dirangkai dengan kondisi lain seperti mask biasa, misalnya (df["suhu_c"].isna()) & (df["ruang"] == "Lab A") untuk baris hilang yang khusus berasal dari Lab A.
Kesalahan umum#
Kesalahan pertama adalah menggunakan and atau or pada mask, yang berakhir ValueError seperti yang diperlihatkan di atas. Perbaikannya adalah operator & dan | yang bekerja per baris. Kesalahan kedua adalah melupakan tanda kurung per kondisi, sehingga & mengikat perbandingan lebih dahulu dan hasilnya TypeError atau baris yang salah. Kesalahan ketiga adalah mencari baris hilang dengan perbandingan kesamaan, misalnya df["suhu_c"] == np.nan, yang selalu menghasilkan mask kosong karena nilai hilang tidak pernah sama dengan apa pun, termasuk dengan dirinya sendiri. Jalankan pembuktiannya pada data yang sudah membawa tanda hilang.
import numpy as np
import pandas as pd
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
print("lolos via == :", (df["suhu_c"] == np.nan).sum())
print("lolos via isna:", df["suhu_c"].isna().sum())lolos via == : 0
lolos via isna: 3Perbaikannya adalah selalu menggunakan isna() atau kebalikannya notna() untuk mendeteksi keberadaan nilai, dan menyimpan mask ke variabel bila kondisinya panjang. Dengan tiga kebiasaan itu, penyaringan boolean menjadi pola yang paling dapat diprediksi di antara semua cara seleksi baris.
Ringkasan#
- Perbandingan kolom menghasilkan mask
Seriesbertipebool, dan mask dipakai padadf[mask]maupundf.loc[mask, daftar_kolom]. - Kondisi majemuk memakai
&dan|dengan tanda kurung pada setiap kondisi, sedangkananddanormemunculkanValueError. - Nilai hilang dideteksi dengan
isna()karena perbandingan kesamaan tidak pernah cocok denganNaN. - Negasi
~membalik mask, sehingga baris yang tidak lolos kondisi dapat diambil tanpa menulis ulang kondisinya.
Referensi#
- Indexing and selecting data — pandas User Guide — bab resmi tentang boolean indexing beserta aturan operator gabungan.
- Working with missing data — pandas User Guide — panduan resmi nilai hilang, termasuk isna dan perilaku NaN pada perbandingan.