DatetimeIndex

Penyaringan tanggal pada DatetimeIndex, termasuk pengindeksan string parsial.

Daftar isi

Topik ini membahas DatetimeIndex, yaitu index baris yang bertipe datetime, beserta cara penyaringannya pada dataset log sensor tiga ruangan. Kolom waktu dijadikan index dengan set_index, lalu baris diambil menurut rentang label, string parsial untuk satu hari atau satu jam, dan jendela jam yang berulang dengan between_time. Setelah membaca, pemilihan baris berdasarkan waktu dapat dilakukan tanpa menyaring kolom satu per satu.

Menjadikan kolom waktu sebagai index#

Method set_index("waktu") menjadikan kolom waktu sebagai label baris dan menghasilkan DatetimeIndex, yaitu index yang menyimpan nilai datetime. Posisi index memberi kolom waktu perlakuan khusus, karena pandas mengenali index bertipe datetime dan menyediakan penyaringan berbasis waktu yang tidak tersedia untuk kolom biasa. Konversi teks ke datetime dilakukan terlebih dahulu lewat parameter parse_dates, sebagaimana dibahas pada topik Konversi datetime, kemudian barulah set_index dipanggil.

python Menjadikan kolom waktu sebagai index baris
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)  # dataset bersama untuk seluruh modul
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"]).set_index("waktu")
print(df.head(3))
print(type(df.index).__name__)
text Keluaran
                           ruang  suhu_c  lembap_pct status_sensor
waktu
2026-01-05 07:00:00  Ruang Arsip    21.5        68.6        normal
2026-01-05 07:15:00        Lab B    21.8        59.1        normal
2026-01-05 07:30:00  Ruang Arsip    22.0        58.1        normal
DatetimeIndex

Keluaran menunjukkan nama waktu berpindah ke posisi label baris di sisi kiri tabel, dan tiga baris pertama berlabel 07.00 sampai 07.30. Pemeriksaan type(df.index).__name__ menegaskan bahwa indexnya kini DatetimeIndex, bukan index angka bawaan. Seluruh penyaringan pada topik ini memakai bentuk tabel yang sama, sehingga blok berikutnya cukup membaca ulang berkas dan memanggil set_index sebelum menyaring.

Penyaringan rentang dengan loc#

Method loc menerima dua label waktu yang dipisah titik dua untuk mengambil seluruh baris pada rentang tersebut. Bentuknya df.loc["2026-01-05 07:00":"2026-01-05 08:00"], dan teksnya ditulis dalam format ISO seperti nilai datetime itu sendiri. Seleksi ini dapat dipadukan dengan seleksi kolom, sehingga tabel hasilnya hanya memuat kolom yang benar-benar dibutuhkan.

python Mengambil rentang satu jam dengan loc
import pandas as pd

df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"]).set_index("waktu")
sel = df.loc["2026-01-05 07:00":"2026-01-05 08:00", ["ruang", "suhu_c"]]
print(sel)
text Keluaran
                           ruang  suhu_c
waktu
2026-01-05 07:00:00  Ruang Arsip    21.5
2026-01-05 07:15:00        Lab B    21.8
2026-01-05 07:30:00  Ruang Arsip    22.0
2026-01-05 07:45:00        Lab B    22.5
2026-01-05 08:00:00        Lab A    24.6

Keluaran memuat lima baris yang berjarak lima belas menit, mulai dari 07.00 sampai 08.00. Kedua ujung rentang ikut terambil, sehingga baris berlabel 07.00 dan 08.00 sama-sama ada pada hasil. Sifat inklusif ini berbeda dengan slicing list Python yang mengabaikan batas kanannya, dan perbedaan itu penting diingat ketika menghitung jumlah baris yang diharapkan dari sebuah rentang.

String parsial untuk satu hari atau satu jam#

String parsial adalah teks tanggal yang dipotong sebagian, dan pandas mengambil semua baris yang jatuh pada periode yang tersirat dari potongan itu. Bentuk df.loc["2026-01-05"] mengambil satu hari penuh, sedangkan df.loc["2026-01-05 07"] mengambil satu jam penuh karena jamnya ikut dinyatakan. Penyaringan ini hanya berlaku pada DatetimeIndex, sehingga konversi pada topik Konversi datetime menjadi syaratnya.

python String parsial untuk satu hari dan satu jam
import pandas as pd

df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"]).set_index("waktu")
sehari = df.loc["2026-01-05"]
print("baris untuk satu hari:", len(sehari))
print(sehari.head(3))
sejam = df.loc["2026-01-05 07"]
print("baris untuk satu jam:", len(sejam))
print(sejam[["ruang", "suhu_c"]])
text Keluaran
baris untuk satu hari: 68
                           ruang  suhu_c  lembap_pct status_sensor
waktu
2026-01-05 07:00:00  Ruang Arsip    21.5        68.6        normal
2026-01-05 07:15:00        Lab B    21.8        59.1        normal
2026-01-05 07:30:00  Ruang Arsip    22.0        58.1        normal
baris untuk satu jam: 4
                           ruang  suhu_c
waktu
2026-01-05 07:00:00  Ruang Arsip    21.5
2026-01-05 07:15:00        Lab B    21.8
2026-01-05 07:30:00  Ruang Arsip    22.0
2026-01-05 07:45:00        Lab B    22.5

Keluaran menunjukkan 68 baris untuk teks satu hari, yaitu seluruh bacaan dari 07.00 sampai 23.45 pada 5 Januari, dan 4 baris untuk teks satu jam, yaitu bacaan 07.00 sampai 07.45. Log berjalan dari pukul 07.00 pada 5 Januari hingga 06.45 pada 6 Januari, sehingga satu hari kalender tidak selalu berisi 96 bacaan. Hubungan teks dan periodenya konsisten, yaitu semakin panjang teksnya, semakin sempit periode yang tercakup.

between_time untuk jendela jam harian#

Method between_time("08:00", "09:00") mengambil baris pada jendela jam yang berulang setiap hari, dengan kedua ujung jendela ikut dihitung secara bawaan. Method ini bekerja pada komponen jam dari index, sehingga tanggalnya boleh berbeda asalkan jamnya jatuh di dalam jendela. Bentuk ini cocok untuk pertanyaan seperti bacaan pada jam operasional tertentu, tanpa perlu menyusun rentang tanggal satu per satu.

python Mengambil jendela jam 08.00 sampai 09.00
import pandas as pd

df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"]).set_index("waktu")
print(df.between_time("08:00", "09:00")[["ruang", "suhu_c"]])
text Keluaran
                           ruang  suhu_c
waktu
2026-01-05 08:00:00        Lab A    24.6
2026-01-05 08:15:00  Ruang Arsip    22.6
2026-01-05 08:30:00  Ruang Arsip    23.4
2026-01-05 08:45:00  Ruang Arsip    25.9
2026-01-05 09:00:00        Lab A    23.5

Keluaran memuat lima baris yang seluruhnya berasal dari 5 Januari, yaitu bacaan 08.00 sampai 09.00. Tidak ada baris dari 6 Januari karena log pada hari itu berhenti pukul 06.45, sehingga jendela 08.00 sampai 09.00 tidak menemui waktunya. Batas atas jendela ikut terambil sebagaimana batas bawahnya, dan perhatikan bahwa between_time tidak menuntut index yang terurut karena pencariannya berdasar komponen jam.

Syarat index terurut#

Penyaringan rentang pada DatetimeIndex mensyaratkan index yang terurut menaik, dan method sort_index() memulihkan urutan tersebut bila sudah rusak. Pengurutan berdasarkan nilai kolom lain, misalnya sort_values("suhu_c"), merusak urutan waktu index, dan pandas menolak rentang string pada index yang tak terurut dengan KeyError. Blok berikut sengaja mengacak urutan baris, menunjukkan penolakannya, lalu memperbaikinya dengan sort_index.

python Penyaringan rentang pada index tak terurut dan perbaikannya
import pandas as pd

df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"]).set_index("waktu")
acak = df.sort_values("suhu_c")
try:
    acak.loc["2026-01-05 07:00":"2026-01-05 08:00", ["ruang", "suhu_c"]]
except KeyError as e:
    print(type(e).__name__, ":", e)
rapi = acak.sort_index()
print(rapi.loc["2026-01-05 07:00":"2026-01-05 08:00", ["ruang", "suhu_c"]])
text Keluaran
KeyError : 'Value based partial slicing on non-monotonic DatetimeIndexes with non-existing keys is not allowed.'
                           ruang  suhu_c
waktu
2026-01-05 07:00:00  Ruang Arsip    21.5
2026-01-05 07:15:00        Lab B    21.8
2026-01-05 07:30:00  Ruang Arsip    22.0
2026-01-05 07:45:00        Lab B    22.5
2026-01-05 08:00:00        Lab A    24.6

Pesan KeyError menegaskan bahwa penyaringan rentang berbasis nilai tidak diizinkan pada DatetimeIndex yang tidak monotonic, yaitu tidak terurut menaik. Setelah sort_index() dijalankan, rentang yang sama menghasilkan lima baris persis seperti pada bagian Penyaringan rentang dengan loc. Kedua method pengurutan ini memiliki tugas yang berbeda, yaitu sort_values mengurutkan baris menurut nilai kolom, sedangkan sort_index mengurutkannya menurut label index.

Kesalahan umum#

Penyaringan string parsial gagal dengan KeyError ketika index belum bertipe datetime, dan pesannya sering disalahartikan sebagai data yang hilang. Bila berkas dibaca tanpa parameter parse_dates, kolom waktu masih bertipe teks, sehingga set_index menghasilkan index teks dan pandas mencari label persis bernama 2026-01-05 yang memang tidak ada. Blok berikut menunjukkan kegagalan itu beserta perbaikannya.

python Penyaringan parsial pada index yang belum bertipe datetime
import pandas as pd

df_teks = pd.read_csv("sensor_log.csv").set_index("waktu")
print("dtype index:", df_teks.index.dtype)
try:
    df_teks.loc["2026-01-05"]
except KeyError as e:
    print(type(e).__name__, ":", e)
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"]).set_index("waktu")
print("baris untuk satu hari:", len(df.loc["2026-01-05"]))
text Keluaran
dtype index: str
KeyError : '2026-01-05'
baris untuk satu hari: 68

Keluaran menunjukkan dtype index str, lalu KeyError: '2026-01-05' yang menunjuk teks yang dicari, dan akhirnya 68 baris setelah parse_dates diberikan pada saat membaca. Perbaikan lainnya adalah konversi lewat pd.to_datetime sebelum set_index, sebagaimana dibahas pada topik Konversi datetime. Pola yang sehat untuk dipegang adalah memastikan dtype index sebelum memakai string parsial, karena pesan errornya tidak selalu mengarah ke penyebab sebenarnya.

Ringkasan#

  • set_index("waktu") menjadikan kolom waktu sebagai label baris dan menghasilkan DatetimeIndex yang mendukung penyaringan berbasis waktu.
  • df.loc["awal":"akhir"] mengambil rentang label waktu dengan kedua ujung ikut terambil, berbeda dari slicing list Python.
  • String parsial seperti "2026-01-05" dan "2026-01-05 07" mengambil satu hari atau satu jam penuh, dan between_time("08:00", "09:00") mengambil jendela jam yang berulang tiap hari.
  • Penyaringan rentang menuntut index terurut, dan string parsial menuntut index bertipe datetime, dengan sort_index() dan parse_dates sebagai perbaikannya.

Referensi#