Indeks Boolean

Penyaringan dengan mask boolean, kondisi majemuk, dan isna pada kondisi.

Daftar isi

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.

python Membangun dataset dengan tanda nilai hilang pada sensor rusak
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())
text Keluaran
baris dengan suhu hilang: 3

Tiga 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.

python Mask dari perbandingan satu kolom
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())
text Keluaran
0    False
1    False
2    False
3    False
Name: suhu_c, dtype: bool
baris lolos: 19

Empat 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.

python Menyaring baris panas beserta kolom yang relevan
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))
text Keluaran
                 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.0

Hasilnya 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.

python Kondisi majemuk yang benar dengan tanda kurung
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"]])
text Keluaran
                 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.3

Hanya 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.

python Dua bentuk salah: kata kunci and dan tanda kurung yang hilang
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))
text Keluaran
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.

python Baris dengan suhu hilang dan baris dengan suhu 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())
text Keluaran
                 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: 93

Tiga 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.

python Perbandingan kesamaan tidak pernah menangkap nilai 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())
text Keluaran
lolos via == : 0
lolos via isna: 3

Perbaikannya 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 Series bertipe bool, dan mask dipakai pada df[mask] maupun df.loc[mask, daftar_kolom].
  • Kondisi majemuk memakai & dan | dengan tanda kurung pada setiap kondisi, sedangkan and dan or memunculkan ValueError.
  • Nilai hilang dideteksi dengan isna() karena perbandingan kesamaan tidak pernah cocok dengan NaN.
  • Negasi ~ membalik mask, sehingga baris yang tidak lolos kondisi dapat diambil tanpa menulis ulang kondisinya.

Referensi#