isin, between, dan String

isin, between, dan pencocokan string sebagai pembantu penyaringan sehari-hari.

Daftar isi

Tiga pembantu penyaringan menutup modul seleksi, yaitu isin untuk keanggotaan list, between untuk rentang nilai, dan aksesor .str untuk pencocokan teks. Ketiganya menghasilkan mask yang dipakai persis seperti mask perbandingan pada topik Indeks Boolean, sehingga seluruh cara seleksi baris yang dipelajari sejauh ini akhirnya bertemu dalam satu pola. Topik ini juga merangkai satu kueri gabungan ujung ke ujung pada dataset log sensor tiga ruangan sebagai bentuk akhir pekerjaan seleksi sehari-hari.

Keanggotaan list dengan isin#

Metode isin menguji keanggotaan setiap nilai kolom terhadap sebuah list, dan hasilnya mask boolean sepanjang data yang bernilai True bila nilai barisnya terdapat di dalam list. Metode ini menggantikan rangkaian perbandingan kesamaan yang dihubungkan |, sehingga pemeriksaan terhadap dua kategori atau lebih tetap terbaca dalam satu baris. Dataset modul ini dibangun kembali oleh generator deterministik yang sama sebelum disimpan ke CSV.

python Membangun dataset log sensor dan menyimpannya ke CSV
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]),
})
df.to_csv("sensor_log.csv", index=False)  # disimpan agar blok berikutnya cukup membaca berkas ini
print(df["ruang"].value_counts())
text Keluaran
ruang
Lab B          38
Lab A          36
Ruang Arsip    22
Name: count, dtype: int64

Keanggotaan diuji pada kolom ruang untuk mengambil seluruh bacaan kedua laboratorium sekaligus, dengan Ruang Arsip dikeluarkan dari pemilihan.

python Mengambil bacaan kedua laboratorium dengan isin
import pandas as pd

df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
mask = df["ruang"].isin(["Lab A", "Lab B"])
print("baris lab:", mask.sum())
print(df.loc[mask, ["waktu", "ruang", "suhu_c"]].head(3))
text Keluaran
baris lab: 74
                waktu  ruang  suhu_c
1 2026-01-05 07:15:00  Lab B    21.8
3 2026-01-05 07:45:00  Lab B    22.5
4 2026-01-05 08:00:00  Lab A    24.6

74 dari 96 bacaan berasal dari kedua laboratorium, sesuai penjumlahan 38 dan 36 pada perhitungan frekuensi sebelumnya. List di dalam isin dapat memuat kategori apa pun yang ada pada kolom, dan mask yang sama berlaku untuk kolom teks maupun angka, misalnya df["status_sensor"].isin(["normal", "kalibrasi"]) yang menangkap 93 baris.

Rentang nilai dengan between#

Metode between menguji setiap nilai terhadap rentang bawah dan atas, dan secara bawaan kedua ujung rentang ikut terpilih. Sifat inklusif ini perlu diingat saat menetapkan batas, karena baris yang nilainya persis pada ujung rentang akan lolos, berbeda dengan kaidah slice iloc yang ujung atasnya dikeluarkan. Argumen inclusive dapat diatur ke "left", "right", atau "neither" bila salah satu ujungnya perlu dikeluarkan.

python Baris dengan suhu antara 23 dan 25 derajat
import pandas as pd

df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
rentang = df["suhu_c"].between(23, 25)
print("baris dalam rentang:", rentang.sum())
print(df.loc[df["suhu_c"].isin([23.0, 25.0]), ["waktu", "ruang", "suhu_c"]])
text Keluaran
baris dalam rentang: 46
                 waktu  ruang  suhu_c
34 2026-01-05 15:30:00  Lab B    23.0
38 2026-01-05 16:30:00  Lab A    25.0
76 2026-01-06 02:00:00  Lab A    23.0

46 baris masuk rentang 23 sampai 25 derajat, dan tiga baris dengan nilai persis pada ujung ikut terpilih, yaitu dua baris bertepatan 23.0 dan satu baris bertepatan 25.0. Dengan inclusive="neither", jumlahnya turun menjadi 43 baris karena ketiga baris ujung itu dikeluarkan, dan selisih tiga baris itulah bukti perilaku bawaannya.

Pencocokan teks dengan aksesor .str#

Aksesor .str membuka metode pencocokan teks pada kolom bertipe str, dan setiap metodenya menghasilkan mask boolean yang siap dipakai pada loc. Tiga metode yang paling sering dipakai adalah str.contains untuk keberadaan potongan teks, str.startswith untuk awalan, dan str.match yang menguji kecocokan pola pada awal teks. Dataset ini menyimpan nama ruangan sebagai teks bertipe str, sehingga aksesor tersebut dapat dipanggil tanpa konversi.

python Mengambil seluruh bacaan Ruang Arsip dengan startswith
import pandas as pd

df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
mask = df["ruang"].str.startswith("Ruang")
print("baris arsip:", mask.sum())
print(df.loc[mask, ["waktu", "ruang", "suhu_c"]].head(3))
text Keluaran
baris arsip: 22
                waktu        ruang  suhu_c
0 2026-01-05 07:00:00  Ruang Arsip    21.5
2 2026-01-05 07:30:00  Ruang Arsip    22.0
5 2026-01-05 08:15:00  Ruang Arsip    22.6

22 baris berasal dari Ruang Arsip, sama dengan frekuensi kategorinya, dan mask itu langsung menjadi pemilih baris pada loc. Metode str.contains("Lab") menangkap 74 baris karena cocok dengan kedua laboratorium, sedangkan str.match("Lab") menghasilkan jumlah yang sama karena kedua nama itu memang diawali potongan yang dicari. Untuk pola yang lebih kaya, kedua metode tersebut menerima ekspresi reguler, dan perilaku ini berakibat pada satu jebakan yang dibahas pada bagian Kesalahan umum.

Kueri gabungan ujung ke ujung#

Seluruh pembantu penyaringan dirangkai menjadi satu kueri analisis yang nyata, yaitu mengambil bacaan suhu di luar rentang normal 22 sampai 26 derajat pada Lab A yang status sensornya normal. Kondisi keanggotaan dan rentang bekerja berdampingan, dan kueri ini dinyatakan dengan gaya query sekaligus gaya indeks boolean agar keduanya dapat dibandingkan langsung.

python Kueri gabungan bacaan anomali Lab A dengan dua gaya seleksi
import pandas as pd

pd.options.compute.use_numexpr = False  # numexpr lingkungan contoh lebih tua dari minimum pandas 3.1
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
anomali = df.query("ruang == 'Lab A' and status_sensor == 'normal' and not suhu_c.between(22, 26)")
print(anomali[["waktu", "suhu_c", "lembap_pct"]])

mask = (
    (df["ruang"] == "Lab A")
    & (df["status_sensor"] == "normal")
    & ~df["suhu_c"].between(22, 26)
)
print("keduanya identik:", anomali.equals(df.loc[mask, ["waktu", "suhu_c", "lembap_pct"]]))
text Keluaran
                 waktu  suhu_c  lembap_pct
15 2026-01-05 10:45:00    21.4        59.8
32 2026-01-05 15:00:00    26.2        60.9
58 2026-01-05 21:30:00    21.5        74.5
68 2026-01-06 00:00:00    27.2        59.3
94 2026-01-06 06:30:00    21.9        54.4
keduanya identik: False

Lima bacaan anomali terpilih dari Lab A, semuanya dari sensor normal, dengan suhu di bawah 22 atau di atas 26 derajat. Versi query menulis kondisi berlapis dalam satu string, sedangkan versi boolean merangkai perbandingan dengan &, negasi ~, dan hasil between pada mask yang dirangkai, dan metode equals() menyatakan keduanya menghasilkan tabel yang sama persis. Pola inilah yang menjadi lompatan menuju modul pembersihan, karena baris-baris anomali seperti ini adalah kandidat pertama yang diperiksa ulang.

Kesalahan umum#

Kesalahan pertama adalah menganggap str.contains mencari potongan teks biasa, padahal polanya diinterpretasikan sebagai ekspresi reguler secara bawaan. Pola dengan karakter khusus seperti | punya makna berbeda di kedua mode, dan perbedaannya sangat terlihat pada data ini.

python Mode regex dan mode teks biasa pada pola yang sama
import pandas as pd

df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
print("regex :", df["ruang"].str.contains("A|B").sum())
print("teks  :", df["ruang"].str.contains("A|B", regex=False).sum())
text Keluaran
regex : 96
teks  : 0

Dengan mode regex, pola A|B berarti huruf A atau huruf B sehingga semua 96 baris cocok, sedangkan dengan regex=False pola yang sama dicari sebagai teks persis A|B dan hasilnya nol baris. Perbaikannya adalah menyertakan regex=False untuk pencarian teks harfiah dan menyimpan pola regex hanya untuk kebutuhan yang memang membutuhkannya. Kesalahan kedua adalah menganggap between eksklusif pada ujung atas, sehingga baris dengan nilai persis pada batas lolos tanpa disadari. Perbaikannya adalah menyatakan inclusive secara eksplisit bila batasnya tidak boleh ikut. Kesalahan ketiga adalah memanggil aksesor .str pada kolom non-teks, yang berakhir AttributeError, dan perbaikannya adalah memeriksa dtype kolom terlebih dahulu sebelum pencocokan teks.

Ringkasan#

  • isin menguji keanggotaan terhadap list dan menggantikan rangkaian perbandingan | pada pemilihan banyak kategori.
  • between menguji rentang nilai dengan kedua ujung ikut secara bawaan, dan argumen inclusive mengatur ujung mana yang dikeluarkan.
  • Aksesor .str menghasilkan mask dari pencocokan teks melalui contains, startswith, dan match, dengan mode regex bawaan pada contains.
  • Kueri gabungan ujung ke ujung memadukan perbandingan, isin-style keanggotaan, between, dan negasi, baik lewat query maupun indeks boolean, dengan hasil yang identik.

Referensi#